# `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`](https://gno.land/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](https://github.com/moul/gno-contracts)** โ€” moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage. **Dependency graph:** ![gno.land/r/moul/x/gsdash/v0 dependency graph](https://raw.githubusercontent.com/moul/gno-contracts/main/_assets/gno.land/r/moul/x/gsdash/v0/deps.png) > ๐Ÿงช **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](https://github.com/moul/gno-contracts/blob/main/DISCLAIMER.md).