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/daily/coinflipduel/v1

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v1
Namespace
moul / x / daily / coinflipduel
Files
5 (README)(gnomod.toml)
Exported functions
4
Module
gno.land/r/moul/x/daily/coinflipduel/v1
gno
0.9

Files (5)

  • README.mdmarkdown
  • gnomod.tomltoml
  • coinflipduel.gnogno
  • coinflipduel_test.gnogno
  • render_example_test.gnogno
coinflipduel_test.gnogno
1package coinflipduel23import (4	"testing"56	"gno.land/p/nt/avl/v0"7	"gno.land/p/nt/testutils/v0"8)910func resetState() {11	duels = avl.Tree{}12	players = avl.Tree{}13	nextID = 014	flipNonce = 015	totalDone = 016	var zero address17	champion = zero18	championWins = 019}2021func TestParseCall(t *testing.T) {22	for _, s := range []string{"heads", "Heads", " h ", "tails", "T"} {23		if _, ok := parseCall(s); !ok {24			t.Fatalf("parseCall(%q) should be valid", s)25		}26	}27	if _, ok := parseCall("sideways"); ok {28		t.Fatal(`parseCall("sideways") should be invalid`)29	}30}3132// Crossing: Challenge and Accept mutate realm state, so the test needs `cur realm`.33func TestChallengeAndAccept(cur realm, t *testing.T) {34	resetState()35	alice := testutils.TestAddress("alice")36	bob := testutils.TestAddress("bob")3738	testing.SetRealm(testing.NewUserRealm(alice))39	Challenge(cross(cur), bob.String(), "heads")4041	if !duels.Has("1") {42		t.Fatal("expected duel #1 to exist")43	}4445	testing.SetRealm(testing.NewUserRealm(bob))46	Accept(cross(cur), "1")4748	v := duels.Get("1")49	d := v.(*duel)50	if d.Status != statusResolved {51		t.Fatalf("Status = %v, want resolved", d.Status)52	}53	if d.Result != "heads" && d.Result != "tails" {54		t.Fatalf("Result = %q, want heads or tails", d.Result)55	}56	if totalDone != 1 {57		t.Fatalf("totalDone = %d, want 1", totalDone)58	}5960	winnerStats := getOrCreate(d.Winner)61	if winnerStats.Wins != 1 {62		t.Fatalf("winner Wins = %d, want 1", winnerStats.Wins)63	}64	if !champion.IsValid() || champion != d.Winner {65		t.Fatal("champion should be the duel winner")66	}67}6869func TestChallengeSelfRejected(cur realm, t *testing.T) {70	resetState()71	alice := testutils.TestAddress("alice")72	testing.SetRealm(testing.NewUserRealm(alice))7374	// Challenge panics inside a cross-realm call; a plain defer/recover in75	// this test does not catch a cross-boundary panic, so use revive().76	rec := revive(func() { Challenge(cross(cur), alice.String(), "heads") })77	if rec == nil {78		t.Fatal("expected panic when challenging yourself")79	}80}8182func TestOnlyOpponentCanAccept(cur realm, t *testing.T) {83	resetState()84	alice := testutils.TestAddress("alice")85	bob := testutils.TestAddress("bob")86	mallory := testutils.TestAddress("mallory")8788	testing.SetRealm(testing.NewUserRealm(alice))89	Challenge(cross(cur), bob.String(), "tails")9091	testing.SetRealm(testing.NewUserRealm(mallory))92	rec := revive(func() { Accept(cross(cur), "1") })93	if rec == nil {94		t.Fatal("expected panic when a non-opponent accepts")95	}96}9798func TestCancel(cur realm, t *testing.T) {99	resetState()100	alice := testutils.TestAddress("alice")101	bob := testutils.TestAddress("bob")102103	testing.SetRealm(testing.NewUserRealm(alice))104	Challenge(cross(cur), bob.String(), "heads")105	Cancel(cross(cur), "1")106107	v := duels.Get("1")108	d := v.(*duel)109	if d.Status != statusCancelled {110		t.Fatalf("Status = %v, want cancelled", d.Status)111	}112}113114// Non-crossing: Render is a plain read.115func TestRenderHome(t *testing.T) {116	resetState()117	out := Render("")118	if out == "" {119		t.Fatal(`Render("") should not be empty`)120	}121}122

Functions

  • Accept(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id string) string

  • Cancel(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id string) string

  • Challenge(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, opponentAddr string, call string) string

  • Render(path string) string

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.