v0 source realm
Package gsdash renders one address's whole GnoSwap footprint on chain, with no indexer and no off-chain query: balanc...
View source
gno.land/r/moul/x/gsdash/v0
One address's whole GnoSwap footprint, read on chain. GNS and xGNS balances, every liquidity position with what it holds at the current price, the swap fees it has accrued, and the emission rewards waiting to be collected. No indexer, no API, no off-chain query: the page is a realm reading other realms.
/r/moul/x/gsdash/v0 the index
/r/moul/x/gsdash/v0:g1manfred... that address
/r/moul/x/gsdash/v0:g1manfred.../from/250 the next window of records
What it reads, and why through those paths
GnoSwap splits every module in two: an unversioned proxy
(r/gnoswap/position) and the implementation
behind it (r/gnoswap/position/v1), swapped at runtime by a version manager. This
realm names only the proxies, so a GnoSwap implementation upgrade does not reach it.
| Section | Read from |
|---|---|
| GNS, xGNS, position NFTs held | r/gnoswap/gns, r/gnoswap/gov/xgns, r/gnoswap/gnft |
| position records, ticks, liquidity, balances, unclaimed fees | r/gnoswap/position |
| who really owns a staked position, and its pending emission | r/gnoswap/staker |
Two things that are not obvious
A staked position's NFT owner is not its owner. Staking transfers the position
NFT to the staker realm, so position.GetPositionOwner answers with that realm's
address for everything staked. The person is named by the deposit record instead,
staker.GetDepositOwner. A dashboard that trusts the NFT owner alone shows an empty
page to everyone who staked, which is most of them.
There is no address-to-positions index in GnoSwap. gnft is a plain GRC721
with no enumerable extension, so finding an address's positions means walking the
stored records and asking each one who owns it. Queries run under a fixed gas
ceiling, so the walk is paged: one page covers 250 records, and the footer links
the next. GnoSwap's own position page takes the same view from the other side,
rendering a keyed lookup and saying it "does not enumerate positions".
The walk is cheap per record and expensive per hit on purpose. Identifying an owner is one tree lookup, or two for a staked position; the price math behind the in-range flag, the token balances and the unclaimed fees costs far more, and runs only for a row that is actually printed.
Record keys are decimal strings, so a window is a slice of the tree in lexicographic order and not a range of IDs. It covers every record either way, which is what the scan needs; do not read an offset as an ID.
Building it
GnoSwap lives on gnoland-1 and in no monorepo examples/, so its packages are
vendored here from the chain:
go -C tools tool gnocontracts vendor -from-chain https://rpc.gno.land
Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.
Dependency graph:

🧪 Highly experimental — potentially vibe-coded. Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: DISCLAIMER.
Package gsdash renders one address's whole GnoSwap footprint on chain, with no indexer and no off-chain query: balances, liquidity positions, what each one is worth right now, and what it has earned but not collected.
It reads GnoSwap through the unversioned proxy paths (r/gnoswap/position and friends) rather than their /vN implementations, so a GnoSwap implementation upgrade does not reach this realm.