PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/moul/x/across/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
moul / x / across
Files
4 (README)(gnomod.toml)
Exported functions
3
Module
gno.land/r/moul/x/across/v0
gno
0.9

Files (4)

  • README.mdmarkdown
  • gnomod.tomltoml
  • across.gnogno
  • across_test.gnogno
across.gnogno
1// Package across reads one address across fifteen other realms that are2// already live, and renders everything they will say about it on one page.3//4// It is a composability demo with a working product hiding inside it. The5// realms it reads were written months apart, by nobody coordinating, and none6// of them knows this one exists. Not a line of them changed to make this7// possible: the only requirement any of them had to meet was NOT declaring8// `private = true`, which is what lets another realm import it at all.9//10// # Why this realm holds no state and extracts no library11//12// Every other realm here splits into a pure `p/` and a thin `r/`. This one13// cannot, and that is the point: its entire content is the wiring. Fifteen14// import lines, one call each, and a table. Extract a library and what is left15// on both sides is empty.16//17// # What it measures, besides balances18//19// The signatures below are the honest half of the demo. Eight of these realms20// hold a per-address balance and they agree on nothing:21//22//	erc20, vestoken, wrapped     BalanceOf(address) uint6423//	pairs/aaa, pairs/bbb         BalanceOf(address) int6424//	grc20faucet                  BalanceOf(symbol string, owner address) int6425//	wikicoin                     BalanceOf(address) uint26//	dice                         RollsOf(addr string) []int27//28// Three integer widths, two signednesses, one that takes the address as a29// string, one that needs a symbol first. Composition works anyway, because a30// gno import is a type-checked contract with a permanent artifact behind it and31// not a call convention anyone has to agree on in advance. It just costs one32// hand-written adapter per source, which is what the report function is.33//34// # The two sources that could not be read35//36//   - r/moul/x/amm/v0 exports SharesOf(keyA, keyB string, owner address), and37//     it routes through mustPool, which PANICS when the pool does not exist.38//     A getter that panics is not composable: fifteen sources on one page means39//     one panicking source takes the whole page down, and a wrapper cannot40//     recover, because recover() does not catch a cross-realm abort. So amm41//     contributes PoolCount() to the index and nothing to a report.42//   - r/moul/demo/vault/v0 exports MyBalance() with no address parameter. It43//     answers for whoever is calling, which from here is this realm, so the44//     value is structurally unreadable from outside.45//46// Neither is a bug in those realms. Both are what a getter looks like when47// nobody has tried to call it from another realm yet.48package across4950import (51	"strconv"52	"strings"5354	"gno.land/p/moul/kit/ui/v0"5556	"gno.land/r/moul/demo/wikicoin/v0"57	"gno.land/r/moul/reactions/v0"58	"gno.land/r/moul/x/amm/v0"59	"gno.land/r/moul/x/daily/dice/v0"60	"gno.land/r/moul/x/daily/erc20/v0"61	"gno.land/r/moul/x/daily/lottery/v0"62	"gno.land/r/moul/x/daily/ratelimitdemo/v0"63	"gno.land/r/moul/x/daily/staking/v0"64	"gno.land/r/moul/x/daily/streak/v0"65	"gno.land/r/moul/x/daily/vestoken/v0"66	"gno.land/r/moul/x/daily/wrapped/v0"67	"gno.land/r/moul/x/grc20faucet/v0"68	"gno.land/r/moul/x/pairs/aaa/v0"69	"gno.land/r/moul/x/pairs/aaabbb/v0"70	"gno.land/r/moul/x/pairs/bbb/v0"71)7273// reactionPage is the page key handed to r/moul/reactions. Reactions are keyed74// on an arbitrary page string rather than on a realm, so a reader of this75// report is asked about the same page /u/moul shows.76const reactionPage = "gno.land/r/moul/home"7778// Self is this realm's own package path, exported so a caller can build a link79// back without hardcoding the version.80const Self = "gno.land/r/moul/x/across/v0"8182// A fact is one answer from one source realm about one address.83//84// zero is carried separately from value because "0" and "none" are the common85// answer and the table is worth reading only for the rows that are not that.86type fact struct {87	source string // package path, without the gno.land/ prefix88	what   string89	value  string90	zero   bool91}9293// Report collects what every wired source says about who.94//95// Every call in here is a plain exported read on another realm: no cur realm,96// no cross, nothing written. A read with no realm parameter is borrowed rather97// than entered (AGENTS.md), so none of these realms even observes a caller.98func Report(who address) []fact {99	out := []fact{}100101	add := func(source, what string, n int64, unit string) {102		v := strconv.FormatInt(n, 10)103		if unit != "" {104			v += " " + unit105		}106		out = append(out, fact{source: source, what: what, value: v, zero: n == 0})107	}108109	// Balances. Eight sources, five signatures.110	add("r/moul/x/daily/erc20/v0", "balance", int64(erc20.BalanceOf(who)), erc20.Symbol())111	add("r/moul/x/daily/vestoken/v0", "liquid balance", int64(vestoken.BalanceOf(who)), vestoken.Symbol())112	add("r/moul/x/daily/wrapped/v0", "wrapped balance", int64(wrapped.BalanceOf(who)), "WGNOT")113	add("r/moul/demo/wikicoin/v0", "balance", int64(wikicoin.BalanceOf(who)), "WIKI")114	add("r/moul/x/pairs/aaa/v0", "balance", aaa.BalanceOf(who), "AAA")115	add("r/moul/x/pairs/bbb/v0", "balance", bbb.BalanceOf(who), "BBB")116	add("r/moul/x/grc20faucet/v0", "balance", grc20faucet.BalanceOf("RED", who), "RED")117	add("r/moul/x/grc20faucet/v0", "balance", grc20faucet.BalanceOf("BLUE", who), "BLUE")118119	// A grant is three numbers, so it does not fit the add helper.120	total, claimed, claimable := vestoken.GrantOf(who)121	out = append(out, fact{122		source: "r/moul/x/daily/vestoken/v0",123		what:   "vesting grant",124		value: strconv.FormatUint(total, 10) + " total, " +125			strconv.FormatUint(claimed, 10) + " claimed, " +126			strconv.FormatUint(claimable, 10) + " claimable",127		zero: total == 0,128	})129130	// Positions.131	add("r/moul/x/pairs/aaabbb/v0", "LP shares", aaabbb.SharesOf(who), "")132	add("r/moul/x/daily/staking/v0", "staked", int64(staking.StakedOf(who)), "")133	add("r/moul/x/daily/staking/v0", "unclaimed rewards", int64(staking.Earned(who)), "")134135	// Activity.136	add("r/moul/x/daily/streak/v0", "current streak", int64(streak.Current(who)), "day(s)")137	add("r/moul/x/daily/streak/v0", "best streak", int64(streak.Best(who)), "day(s)")138	add("r/moul/x/daily/dice/v0", "dice rolled", int64(len(dice.RollsOf(who.String()))), "")139	add("r/moul/x/daily/ratelimitdemo/v0", "rate-limit tokens left", int64(ratelimitdemo.Tokens(who)), "")140141	entered := "no"142	if lottery.HasEntered(who) {143		entered = "yes, round " + strconv.Itoa(lottery.CurrentRound())144	}145	out = append(out, fact{146		source: "r/moul/x/daily/lottery/v0",147		what:   "entered the lottery",148		value:  entered,149		zero:   !lottery.HasEntered(who),150	})151152	// reactions answers with a palette key, already validated at write time, so153	// it never carries caller markdown into this table.154	react := reactions.ReactionOf(reactionPage, who)155	shown := react156	if shown == "" {157		shown = "none"158	}159	out = append(out, fact{160		source: "r/moul/reactions/v0",161		what:   "reaction on " + reactionPage,162		value:  shown,163		zero:   react == "",164	})165166	return out167}168169// sourceRealms is every realm this one imports for its data, in import order.170// It is the single place the count comes from: the index table has one row per171// entry and TestSourcesCoverReport checks that Report names nothing else.172//173// Fifteen entries, which is the number the prose says. TestSourceCount pins it.174var sourceRealms = []string{175	"r/moul/x/daily/erc20/v0",176	"r/moul/x/daily/vestoken/v0",177	"r/moul/x/daily/wrapped/v0",178	"r/moul/demo/wikicoin/v0",179	"r/moul/x/pairs/aaa/v0",180	"r/moul/x/pairs/bbb/v0",181	"r/moul/x/grc20faucet/v0",182	"r/moul/x/pairs/aaabbb/v0",183	"r/moul/x/amm/v0",184	"r/moul/x/daily/staking/v0",185	"r/moul/x/daily/streak/v0",186	"r/moul/x/daily/dice/v0",187	"r/moul/x/daily/lottery/v0",188	"r/moul/x/daily/ratelimitdemo/v0",189	"r/moul/reactions/v0",190}191192// Sources reports how many realms this one reads.193func Sources() int { return len(sourceRealms) }194195func Render(path string) string {196	if path == "" {197		return renderIndex()198	}199	addr := address(path)200	if !addr.IsValid() {201		return "# across\n\n" + ui.Empty(ui.Inline(ui.Short(path))+" is not a valid address.") +202			"\n[back to the index](/r/moul/x/across/v0)\n"203	}204	return renderAddress(addr)205}206207func renderAddress(who address) string {208	var b strings.Builder209	b.WriteString("# across: " + ui.AddrFull(who) + "\n\n")210	b.WriteString("What " + strconv.Itoa(Sources()) + " independently deployed realms say about this address. ")211	b.WriteString("None of them was changed to answer.\n\n")212213	facts := Report(who)214215	live := ui.NewTable("source", "fact", "value")216	quiet := 0217	for _, f := range facts {218		if f.zero {219			quiet++220			continue221		}222		live.Row("[`"+f.source+"`](/"+f.source+")", f.what, f.value)223	}224225	if live.Len() == 0 {226		b.WriteString(ui.Empty("Every one of the " + strconv.Itoa(len(facts)) +227			" reads came back empty. This address has never touched any of them."))228		b.WriteString("\n")229	} else {230		b.WriteString("## Answers\n\n")231		b.WriteString(live.String())232		b.WriteString("\n")233		b.WriteString(strconv.Itoa(quiet) + " of " + strconv.Itoa(len(facts)) +234			" reads came back empty and are hidden.\n\n")235	}236237	b.WriteString("[back to the index](/r/moul/x/across/v0)\n")238	return b.String()239}240241func renderIndex() string {242	var b strings.Builder243	b.WriteString("# across\n\n")244	b.WriteString("One address, read across " + strconv.Itoa(Sources()) + " realms that are already on chain.\n\n")245	b.WriteString("Open `/r/moul/x/across/v0:<address>` to get the report. ")246	b.WriteString("Example: [/r/moul/x/across/v0:" + exampleAddr + "](/r/moul/x/across/v0:" + exampleAddr + ").\n\n")247248	b.WriteString("## Why this realm exists\n\n")249	b.WriteString("A gno realm that does not declare `private = true` can be imported by any ")250	b.WriteString("other realm, forever, at a path that can never be replaced. That makes every ")251	b.WriteString("exported read on it a permanent public API. This realm is what happens when ")252	b.WriteString("somebody actually uses " + strconv.Itoa(Sources()) + " of them at once.\n\n")253	b.WriteString("Nothing here was negotiated. No registry, no interface, no shared base ")254	b.WriteString("package, no version handshake, and no change to any source realm.\n\n")255256	b.WriteString("## The sources, and what each one is showing right now\n\n")257	t := ui.NewTable("realm", "global reading")258	t.Row("[`r/moul/x/daily/erc20/v0`](/r/moul/x/daily/erc20/v0)",259		erc20.Symbol()+" supply "+strconv.FormatUint(erc20.TotalSupply(), 10))260	t.Row("[`r/moul/x/daily/vestoken/v0`](/r/moul/x/daily/vestoken/v0)",261		vestoken.Symbol()+" supply "+strconv.FormatUint(vestoken.TotalSupply(), 10))262	t.Row("[`r/moul/x/daily/wrapped/v0`](/r/moul/x/daily/wrapped/v0)",263		"wrapped supply "+strconv.FormatUint(wrapped.TotalSupply(), 10))264	t.Row("[`r/moul/demo/wikicoin/v0`](/r/moul/demo/wikicoin/v0)", "per-address balances only")265	t.Row("[`r/moul/x/pairs/aaa/v0`](/r/moul/x/pairs/aaa/v0)",266		"AAA supply "+strconv.FormatInt(aaa.TotalSupply(), 10))267	t.Row("[`r/moul/x/pairs/bbb/v0`](/r/moul/x/pairs/bbb/v0)",268		"BBB supply "+strconv.FormatInt(bbb.TotalSupply(), 10))269	t.Row("[`r/moul/x/grc20faucet/v0`](/r/moul/x/grc20faucet/v0)",270		"RED supply "+strconv.FormatInt(grc20faucet.TotalSupply("RED"), 10)+271			", BLUE supply "+strconv.FormatInt(grc20faucet.TotalSupply("BLUE"), 10))272	t.Row("[`r/moul/x/pairs/aaabbb/v0`](/r/moul/x/pairs/aaabbb/v0)",273		"LP shares "+strconv.FormatInt(aaabbb.TotalShares(), 10))274	t.Row("[`r/moul/x/amm/v0`](/r/moul/x/amm/v0)",275		strconv.Itoa(amm.PoolCount())+" pool(s), index only (see below)")276	t.Row("[`r/moul/x/daily/staking/v0`](/r/moul/x/daily/staking/v0)", "per-address stake and rewards")277	t.Row("[`r/moul/x/daily/streak/v0`](/r/moul/x/daily/streak/v0)",278		"day "+strconv.FormatInt(streak.Day(), 10))279	t.Row("[`r/moul/x/daily/dice/v0`](/r/moul/x/daily/dice/v0)",280		strconv.Itoa(dice.Total())+" roll(s) all time")281	t.Row("[`r/moul/x/daily/lottery/v0`](/r/moul/x/daily/lottery/v0)",282		"round "+strconv.Itoa(lottery.CurrentRound())+", "+283			strconv.Itoa(lottery.NumEntrants())+" entrant(s)")284	t.Row("[`r/moul/x/daily/ratelimitdemo/v0`](/r/moul/x/daily/ratelimitdemo/v0)", "per-address bucket")285	t.Row("[`r/moul/reactions/v0`](/r/moul/reactions/v0)",286		strconv.Itoa(reactions.Pages())+" page(s) reacted to")287	b.WriteString(t.String())288	b.WriteString("\n")289290	b.WriteString("## What it cost\n\n")291	b.WriteString("Eight of these hold a per-address balance, and they share no signature: ")292	b.WriteString("`uint64` three times, `int64` twice, `uint` once, one that wants a symbol ")293	b.WriteString("before the address, one that wants the address as a `string`. Every source ")294	b.WriteString("therefore needs its own adapter line. That is the whole cost, and it is paid ")295	b.WriteString("once by the reader rather than up front by fifteen authors.\n\n")296297	b.WriteString("## The two that could not be read\n\n")298	b.WriteString("- `r/moul/x/amm/v0` routes `SharesOf` through a helper that panics on an ")299	b.WriteString("unknown pool. One panicking source takes down a page built from " +300		strconv.Itoa(Sources()) + ", and ")301	b.WriteString("`recover()` does not catch a cross-realm abort, so only its `PoolCount()` is ")302	b.WriteString("safe to call from here.\n")303	b.WriteString("- `r/moul/demo/vault/v0` exports `MyBalance()` with no address parameter. It ")304	b.WriteString("answers for its caller, which from here is this realm.\n\n")305	b.WriteString("Neither is a bug. Both are what a getter looks like before anyone has tried ")306	b.WriteString("to call it from another realm.\n")307308	return b.String()309}310311// exampleAddr is moul's address, used only to give the index a link that312// resolves to a real report instead of an empty one.313const exampleAddr = "g1manfred47kzduec920z88wfr64ylksmdcedlf5"314

Functions

  • Render(path string) string

  • Report(who string) []gno.land/r/moul/x/across/v0.fact

  • Sources() int

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

Rendered

RenderedRawgnoweb ↗

vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.