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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

v1 source realm

Package hollowmere is the on-chain slice of Book One, "The Three Ember Seeds" -- the adventure's own chain record, se...

Overview

Package hollowmere is the on-chain slice of Book One, "The Three Ember Seeds" -- the adventure's own chain record, separate from garden/v2's pet-care record, per the owner's ask: "the adventure game needs chain features."

Authored and tested without gnokey or any key material, per this assignment's own brief. Whether and when this package has actually been deployed is deliberately not asserted here: this comment ships on chain exactly as written the moment it is deployed, and a realm cannot be edited afterwards, so a "not deployed yet" sentence here would go permanently stale at the exact moment it stopped being true -- see garden/v2/gnomod.toml's own history for why this is a real failure mode, not a hypothetical one. Deploy status belongs in DECISIONS.md and STATUS.md, which can still be edited after the fact.

============================================================================ THE HONESTY PROBLEM THIS PACKAGE EXISTS INSIDE -- READ THIS FIRST ============================================================================

The adventure's levels run in the browser. This chain cannot watch a player solve the rune-rhyme puzzle, bonk the Great Mothkin three times, or do anything else Book One's plan describes -- it can only watch a wallet sign a transaction that ASSERTS those things happened. The plan itself says this plainly: "the levels run in the browser, so a determined cheat can poke at them" (pack-update/01-adventure-plan/book-one-plan.md, "Risks and decisions for Seán").

So this package is commented, named and worded throughout to make that limit impossible to miss -- carried by the comments, the event name, the type names and Render's own wording, not by any single exported function's name in isolation (a player signing ClearChapter(1, 1) in a wallet sees that call and nothing else; the honesty framing has to already live in the surrounding names and docs, because there is no comment attached to a signing prompt):

  • ClearChapter does not "verify" or "check" a clear. It records a CLAIM: this address says it cleared this chapter, and the chain stamps that claim with the block's own timestamp. Nothing here replays a puzzle, checks an input log, or asks the browser for proof of anything. The function's own comment says so; the bare function name a wallet shows does not carry this by itself.
  • bookOneClaim, the storage type, and claims, the tree that holds it, are named for what they are: a ledger of claims, not a record of verified outcomes.
  • The emitted event is named ChapterClaimed, not ChapterCleared or ChapterVerified.
  • Render's own wording repeats this to the one audience who will actually read it: a player looking at their own public page.

What this DOES genuinely give the game, worth having even though it is not refereed: the record is public, permanent, timestamped by the chain rather than the client, tied to a wallet rather than a browser's local storage, and readable by anyone without trusting gnotchi.com's server to tell the truth. For a cosy single-player adventure with nothing to win from another player's loss, that is a sound trade. See NOTES.md for the full writeup of why the owner's narrower ask (chapter purchase, the daily burrow, players' notes) is deliberately NOT built here, rather than half-built to look more complete than it is.

============================================================================ SCOPE -- what this package is, and deliberately is not ============================================================================

Built: chapter-completion claims (ClearChapter), Ember Seeds derived from those claims (never accepted as an input), a per-address progress read (BookOneClaim), and a public Render page.

NOT built, on purpose, not half-built: chapter purchase (nothing is for sale here; this package handles no money at all, enforced the same way garden/v2 does, below), the daily burrow and its leaderboard (needs a dungeon generator that doesn't exist yet), and players' notes (stored free text on a permanent public page re-opens the hostile-name problem garden/garden.gno's own NOTES.md already has open, and deserves its own design pass rather than a rushed one here). See NOTES.md for the full reasoning on each.

============================================================================ WHY THIS NEVER CALLS recover() ============================================================================

This package calls no grc721 ledger, mints nothing, and has no transfer hook to protect -- the specific recover()-undoes-a-soulbound-guarantee trap garden/garden.gno's own SECURITY note documents does not literally apply here, because there is no ledger write to re-expose. But the underlying reason not to recover() is the same one stated above in different words: this package's entire credibility is "the chain only ever records a claim that fully passed every check in ClearChapter below." Every mutating path in this file validates completely BEFORE touching any stored claim (see ClearChapter's own comment for the exact validate-then-commit sequence), so an uncaught panic already guarantees the Gno/Cosmos SDK transaction boundary discards the whole failed call with no partial claim ever written. A recover() anywhere in this file -- even one added later for an unrelated reason -- could let a claim that failed a check halfway through land anyway, which is exactly the "the chain checked something it didn't" impression this package's own doc above insists it must never give. Don't add one.

Functions 5

func BookOneClaim

Action
1func BookOneClaim(addr address) (highestChapterClaimed, chapter1ClaimedAt, chapter2ClaimedAt, chapter3ClaimedAt, chapter4ClaimedAt, emberSeeds int64, found bool)
source

BookOneClaim is the progress read for one address: what it has claimed in Book One, and the Ember Seed count derived from those claims. found is false if this address has never had a ClearChapter call accepted for Book One at all.

func ClaimantsPage

Action
1func ClaimantsPage(offset, limit int) []string
source

ClaimantsPage is the paginated enumerator claims needed to be genuinely publicly readable, not just publicly readable one known address at a time. It returns up to limit claim keys (each claimKey(address, book), i.e. "<address>:<book>") in the claims tree's own stable order, starting at offset -- the same (key, value) order claims.IterateByOffset itself walks, which never changes for a fixed tree.

limit is CLAMPED to maxClaimantsPageSize rather than rejected outright, so a caller that asks for too much still gets a gas-bounded page back instead of an aborted call; offset and limit are otherwise rejected if non-positive/negative, since those are caller mistakes with no sane page to return.

Paging with offset 0, then offset+len(returned page), ... until a page shorter than its own requested limit comes back, covers every claimant exactly once, in this stable order, with no duplicates and no gaps, for any snapshot where claims does not grow between calls -- see hollowmere_test.gno's own paging test, which proves this directly rather than assuming it from the underlying avl.Tree's own doc comment.

func ClearChapter

crossing Action
1func ClearChapter(cur realm, book, chapter int64)
source

ClearChapter records that the calling address CLAIMS to have cleared this chapter of this book. See the package doc above for what this is and is not: a timestamped, public, permanent claim, never a verified outcome.

Accepts no coins (this package handles no money at all; see NOTES.md for why chapter purchase is out of scope entirely, not half-built). Chapters must clear in strict order, starting from 1, and each chapter may be claimed at most once per address -- both enforced by the single comparison below against highestChapterClaimed, the same way garden/v2 favours one invariant that closes several hostile cases over several separate ad hoc checks (see that file's SaveDay comment). Ember Seeds are never a parameter here or anywhere in this package: see emberSeedsFor for how they are derived instead.

ATOMICITY: every check below runs to completion before anything is written. work is a plain value copy of this address's existing claim (or the zero value, if this is its first), taken after every validation has already passed; the only thing that happens to it is the two-field update at the bottom, so a panic anywhere above that point leaves the persisted claim -- if any -- completely untouched. This mirrors garden/v2's SaveDay pattern deliberately: a plain value copy, not a recover()-and-rollback. See the package doc for why recover() is never the right tool here either.

func Render

1func Render(path string) string
source

Render gives each player a public page on gno.land. Path validated with address(path).IsValid() before anything derived from it is echoed back -- the same guard garden/v2's own Render uses, and for the same reason: an invalid path must get a generic refusal, never a page built out of attacker-controlled text.

func TotalClaimants

Action
1func TotalClaimants() int64
source

TotalClaimants returns the number of addresses with at least one accepted chapter claim in Book One. Everything claims holds is already public via Render (there is no privacy cost to exposing it), but before this function the only way to reach this exact number was BookOneClaim(someKnownAddress) for one address at a time, or string-parsing the overview page Render("") returns. Neither lets another realm -- a future Book Two, a shop, a leaderboard -- enumerate or even count claimants, which is a real limitation for a ledger whose entire stated purpose is being publicly readable. See ClaimantsPage below for the enumerator this same gap needed.

Dependencies

Source Files 2