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.

example_test.gno

4.70 Kb · 104 lines
  1package reaper
  2
  3import (
  4	"strings"
  5
  6	"gno.land/p/nym-moultest123/x/storagecost/v0"
  7	"gno.land/p/nt/ufmt/v0"
  8)
  9
 10// Every Example in this file is a *query*, and that is a constraint rather
 11// than a choice: an example function takes no arguments, so it never receives
 12// a `cur realm` and can never call Post, Reap or Compact. What is left is
 13// exactly the surface a reader of the live realm has without a key, so each
 14// one carries the `vm/qeval` line that produces the same answer on chain:
 15//
 16//	gnokey query vm/qeval -remote https://rpc.gno.land \
 17//	  -data 'gno.land/r/nym-moultest123/x/reaper/v0.<expr>'
 18//
 19// The board is empty by the time these run, because every Test in this
 20// package drains what it posted and examples run after all of them.
 21
 22// ExampleRender pins the page's skeleton: the title, the two sections that are
 23// always present, and the footer crediting the two packages that own the parts
 24// this realm does not.
 25//
 26//	vm/qrender  gno.land/r/nym-moultest123/x/reaper/v0:
 27//
 28// It deliberately prints only the invariant lines. Everything interesting on
 29// the page is priced from the current block height and the notes outstanding,
 30// and an Example runs after every Test in the package and sees whatever state
 31// they left. The variable half is pinned by TestRenderShowsTheBountyAndTheReapLink
 32// instead, which controls the board first.
 33func ExampleRender() {
 34	for _, line := range strings.Split(Render(""), "\n") {
 35		switch {
 36		case strings.HasPrefix(line, "# "),
 37			strings.HasPrefix(line, "## "),
 38			strings.HasPrefix(line, "A noticeboard"),
 39			strings.HasPrefix(line, "The arithmetic is"):
 40			print(line + "\n")
 41		}
 42	}
 43	// Output:
 44	// # Reaper
 45	// A noticeboard whose garbage is a standing bounty. Posting a note locks a storage deposit. Once the note expires, anyone can delete it and the chain refunds that deposit **to whoever signs the deleting transaction**.
 46	// ## On the table right now
 47	// ## Board
 48	// The arithmetic is [p/moul/x/storagecost](/p/nym-moultest123/x/storagecost/v0); the storage is [p/moul/ulist](/p/nym-moultest123/ulist/v1), whose `Compact` reclaims dead nodes without moving a live index. Byte figures on this page are estimates from payload length: no stdlib call exposes a realm's real locked storage.
 49}
 50
 51// ExampleReapable is the poll a reaping bot runs before it spends anything:
 52// three counters, three queries, no key and no gas.
 53//
 54//	vm/qeval  gno.land/r/nym-moultest123/x/reaper/v0.Live()
 55//	vm/qeval  gno.land/r/nym-moultest123/x/reaper/v0.Reapable()
 56//	vm/qeval  gno.land/r/nym-moultest123/x/reaper/v0.Compactable()
 57//
 58// Reapable and Compactable are separate numbers because reaping and
 59// compacting are separate transactions, and compaction returns nothing at all
 60// while a live note still sits below the dead ones. A bot that sees
 61// `reapable 0, compactable 0` should not sign anything, which is the answer
 62// here.
 63func ExampleReapable() {
 64	print(ufmt.Sprintf("live %d, reapable %d, compactable %d\n",
 65		Live(), Reapable(), Compactable()))
 66	// Output:
 67	// live 0, reapable 0, compactable 0
 68}
 69
 70// ExampleBounty is the single query that decides whether reaping is worth
 71// doing, and on an empty board it has to refuse to advertise a profit.
 72//
 73//	vm/qeval  gno.land/r/nym-moultest123/x/reaper/v0.Bounty().String()
 74//
 75// Fee is what the reaping transaction costs at the floor gas price, and the
 76// chain charges it whether or not anything is freed. BreakEven turns that fee
 77// back into bytes: free fewer than 50 and the reaper is paying to tidy up.
 78// That threshold, not the size of the board, is what makes the mechanism a
 79// market rather than a chore.
 80func ExampleBounty() {
 81	print(Bounty().String() + "\n")
 82	// Output:
 83	// 0 bytes, refunds 0 GNOT against 0.005 GNOT of gas, break-even 50 bytes: not worth it yet
 84}
 85
 86// ExampleBounty_worth is the same query answered by a board worth draining:
 87// ten expired notes of a kilobyte each.
 88//
 89// It recomputes the quote instead of posting, because an example has no
 90// `cur realm` to post with. The arithmetic is the one Bounty applies, so the
 91// numbers are the ones the live query would return with that board on it.
 92//
 93// This is the whole concept in two lines. The poster locked 1.8944 GNOT to
 94// occupy that space; a stranger who never posted anything spends 0.005 GNOT of
 95// gas to delete it and the chain hands them the deposit. Nobody minted a
 96// token, and no pool was funded.
 97func ExampleBounty_worth() {
 98	q := storagecost.EvaluateAtFloor(storagecost.EstimateBytes(10*1024), gasWantedReap)
 99	print(q.String() + "\n")
100	print(ufmt.Sprintf("the reaper is paid %dx what the transaction costs\n", q.Refund/q.Fee))
101	// Output:
102	// 18944 bytes, refunds 1.8944 GNOT against 0.005 GNOT of gas, break-even 50 bytes: worth 1.8894 GNOT
103	// the reaper is paid 378x what the transaction costs
104}