Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

README.md

3.43 Kb · 73 lines

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:

gno.land/r/moul/x/gsdash/v0 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.