Transaction
5362A778FB2EF1…69457D8D5D52
Block 26,362 · index 0 · indexed
Summary
- Hash
- 5362A778FB2EF1BDC5A642199D00DECBB1BE340C587151FFA60669457D8D5D52
- Block
- 26,362
- Size
- 7048 bytes
- Gas used
- 10,950,176 / 13,140,271
- Fee
- 1000000ugnot
- Memo
- gnopublish
- Status
- success
Messages
Arguments · 9
- #1leaderboard
- #2README.md
- #3# 🏆 Leaderboard > ⚠️ **Experimental — generated with no human supervision.** This realm was > produced automatically by an MCP-driven agent to exercise the gno MCP server > and tooling, and to generate test content for gno compilers, linters and > formatters. **Not audited. Not for production.** Full context & folder README: > [r/moul/x/daily](https://github.com/moul/gno-contracts/blob/main/r/moul/x/daily/README.md) --- An on-chain score leaderboard realm for gno.land (sapphire / gno 0.9). Any account can accumulate points with `AddPoints(n)` and optionally attach a display name with `SetName(name)`. `Render` returns a Markdown table ranked by points descending — gold/silver/bronze medals for the top three — plus the total player count. State is kept in an `avl.Tree` so rendering is deterministic across nodes. **Realm path:** `gno.land/r/REPLACE_ADDR/leaderboard` ## Public API | Function | Kind | Description | | --- | --- | --- | | `AddPoints(cur realm, n int)` | crossing (tx) | Add `n` (> 0) points to the caller's total. | | `SetName(cur realm, name string)` | crossing (tx) | Set the caller's display name (≤ 32 bytes; empty clears it). | | `Render(path string) string` | view | Ranked Markdown leaderboard. | ## Example calls ```sh # Add 10 points to your total gnokey maketx call \ -pkgpath "gno.land/r/REPLACE_ADDR/leaderboard" \ -func AddPoints -args 10 \ -gas-fee 1000000ugnot -gas-wanted 2000000 \ -broadcast -chainid sapphire-1 -remote <rpc> <keyname> # Set your display name gnokey maketx call \ -pkgpath "gno.land/r/REPLACE_ADDR/leaderboard" \ -func SetName -args "Alice" \ -gas-fee 1000000ugnot -gas-wanted 2000000 \ -broadcast -chainid sapphire-1 -remote <rpc> <keyname> ``` View the rendered leaderboard in gnoweb at `/r/REPLACE_ADDR/leaderboard`, or query it: ```sh gnokey query "vm/qrender" -data "gno.land/r/REPLACE_ADDR/leaderboard:" -remote <rpc> ``` <!-- BEGIN GNOCONTRACTS FOOTER (generated by `make readmes`; do not edit below) --> --- 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:**  > 🧪 **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). <!-- END GNOCONTRACTS FOOTER -->
- #4gnomod.toml
- #5module = "gno.land/r/moul/x/daily/leaderboard/v0" gno = "0.9"
- #6leaderboard.gno
- #7// Package leaderboard is an on-chain score leaderboard realm. // // Any account can accumulate points via AddPoints and (optionally) attach a // display name with SetName. Render produces a ranked Markdown table sorted by // points descending, with medals for the top three players. package leaderboard import ( "sort" "strconv" "chain/runtime/unsafe" "gno.land/p/nt/avl/v0" ) // player holds the accumulated state for a single address. type player struct { addr address name string points int } // players maps address string -> *player. An avl.Tree gives deterministic // iteration (unlike a Go map) so Render output is stable across nodes. var players avl.Tree // get returns the stored *player for addr, creating one if absent. func get(addr address) *player { key := addr.String() if v := players.Get(key); v != nil { return v.(*player) } p := &player{addr: addr} players.Set(key, p) return p } // caller returns the address of the account that invoked the current tx. // unsafe.PreviousRealm() is the origin user for a MsgCall entry point. func caller() address { return unsafe.PreviousRealm().Address() } // AddPoints adds n points to the caller's total. n must be positive. // // Crossing function: MsgCall dispatches only to crossing functions, and the // cur.IsCurrent() check authenticates the live call frame before we trust the // caller identity derived from it. func AddPoints(cur realm, n int) { if !cur.IsCurrent() { panic("spoofed realm") } if n <= 0 { panic("points must be positive") } p := get(caller()) p.points += n } // SetName attaches a display name (max 32 bytes) to the caller. Passing an // empty string clears the name and falls back to the address in Render. func SetName(cur realm, name string) { if !cur.IsCurrent() { panic("spoofed realm") } if len(name) > 32 { panic("name too long (max 32)") } get(caller()).name = name } // display returns the player's name, or a shortened address if unnamed. func (p *player) display() string { if p.name != "" { return p.name } s := p.addr.String() if len(s) > 12 { return s[:8] + "…" + s[len(s)-4:] } return s } // byRank implements sort.Interface, ranking players by points descending with // ties broken by address so the order is deterministic across nodes. The gno // sort package exposes Sort/Stable over an Interface — there is no sort.Slice. type byRank []*player func (r byRank) Len() int { return len(r) } func (r byRank) Swap(i, j int) { r[i], r[j] = r[j], r[i] } func (r byRank) Less(i, j int) bool { if r[i].points != r[j].points { return r[i].points > r[j].points } return r[i].addr.String() < r[j].addr.String() } // snapshot collects all players into a slice ranked by points descending. func snapshot() []*player { out := make([]*player, 0, players.Size()) players.Iterate("", "", func(_ string, v any) bool { out = append(out, v.(*player)) return false }) sort.Stable(byRank(out)) return out } // medal returns the emoji for a given zero-based rank, or "" past the podium. func medal(rank int) string { switch rank { case 0: return "🥇" case 1: return "🥈" case 2: return "🥉" default: return "" } } // Render produces the Markdown leaderboard. It is NOT a crossing function // (read-only view, no cur realm parameter). func Render(path string) string { ranked := snapshot() out := "# 🏆 Leaderboard\n\n" if len(ranked) == 0 { out += "_No players yet. Call `AddPoints(n)` to get on the board._\n" return out } out += "Total players: **" + strconv.Itoa(len(ranked)) + "**\n\n" out += "| Rank | Player | Points |\n" out += "| ---: | :--- | ---: |\n" for i, p := range ranked { rankCell := medal(i) if rankCell == "" { rankCell = strconv.Itoa(i + 1) } out += "| " + rankCell + " | " + p.display() + " | " + strconv.Itoa(p.points) + " |\n" } return out }
- #8/gno.MemPackageType
- #9 MPUserProd
Result log
msg:0,success:true,log:,events:[]