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/akkadia/beta/lotto

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
lotto
Namespace
akkadia / beta
Files
7 (gnomod.toml)
Exported functions
5
Module
gno.land/r/akkadia/beta/lotto
gno
0.9

Files (7)

  • gnomod.tomltoml
  • lotto.gnogno
  • render.gnogno
  • validation.gnogno
  • lotto_test.gnogno
  • render_test.gnogno
  • setup_test.gnogno
render_test.gnogno
1package lotto23import (4	"net/url"5	"strconv"6	"strings"7	"testing"8

Functions

  • AddNumber(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}, owner string, number uint64)

  • DeleteAll(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})

  • GetNumberCount(number uint64, owner string) uint64

  • ListOwnersByNumber(number uint64, afterOwner string, limit int) []map[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.

9 "gno.land/p/nt/testutils/v0"
10 "gno.land/p/nt/uassert/v0"
11)
12
13func TestRenderInput(cur realm, t *testing.T) {
14 setupLotto(cross(cur))
15 home := Render("")
16 uassert.True(t, strings.Contains(home, "# AKKADIA Lotto"))
17 uassert.True(t, strings.Contains(home, `<gno-form path="number">`))
18 uassert.True(t, strings.Contains(home, `name="number"`))
19 for _, tc := range []struct{ path, message string }{
20 {"%", "Invalid URL"},
21 {"number?number=%zz", "Invalid query"},
22 {"unknown", "Page not found"},
23 {"number", "Number is required"},
24 {"number?number=-1", "Invalid number"},
25 {"number?number=1.5", "Invalid number"},
26 {"number?number=18446744073709551616", "Invalid number"},
27 {"number?number=" + url.QueryEscape(`<script>alert(1)</script>`), "Invalid number"},
28 {"number?number=1&afterOwner=" + url.QueryEscape(`[x](javascript:alert(1))`), "Invalid cursor address"},
29 {"number?number=1&afterOwner=invalid", "Invalid cursor address"},
30 } {
31 result := Render(tc.path)
32 uassert.True(t, strings.Contains(result, tc.message))
33 uassert.True(t, strings.Contains(result, `<gno-form path="number">`))
34 uassert.False(t, strings.Contains(result, "<script>"))
35 uassert.False(t, strings.Contains(result, "javascript:"))
36 }
37 for _, number := range []string{"0", "18446744073709551615"} {
38 result := Render("number?number=" + number)
39 uassert.True(t, strings.Contains(result, "## Number "+number+"\n"))
40 uassert.True(t, strings.Contains(result, "No owners on this page."))
41 uassert.False(t, strings.Contains(result, "[Next]"))
42 }
43 uassert.Equal(t, holdings.Size(), 0)
44}
45
46func TestRenderPagination(cur realm, t *testing.T) {
47 setupLotto(cross(cur))
48 for i := 0; i < 41; i++ {
49 testing.SetRealm(testing.NewUserRealm(testAdmin))
50 owner := testutils.TestAddress("lottoRender" + strconv.Itoa(i))
51 AddNumber(cross(cur), owner, 123)
52 AddNumber(cross(cur), owner, 123)
53 }
54 testing.SetRealm(testing.NewUserRealm(testAdmin))
55 AddNumber(cross(cur), testOther, 1234)
56 route := "number?number=000123"
57 afterOwner := ""
58 for _, expectedCount := range []int{20, 20, 1} {
59 expected := ListOwnersByNumber(123, afterOwner, 20)
60 result := Render(route)
61 uassert.True(t, strings.Contains(result, "## Number 123\n"))
62 uassert.True(t, strings.Contains(result, "[Home](./lotto:)"))
63 uassert.False(t, strings.Contains(result, testOther.String()))
64 uassert.Equal(t, strings.Count(result, " | 2 |\n"), expectedCount)
65 uassert.Equal(t, strings.Contains(result, "[First page]"), afterOwner != "")
66 previous := -1
67 for _, item := range expected {
68 position := strings.Index(result, "| "+item["owner"]+" | 2 |")
69 uassert.True(t, position > previous)
70 previous = position
71 uassert.Equal(t, GetNumberCount(123, address(item["owner"])), uint64(2))
72 }
73 if expected[0]["nextOwner"] != "" {
74 route = "number?number=123&afterOwner=" + url.QueryEscape(expected[0]["nextOwner"])
75 uassert.True(t, strings.Contains(result, "[Next](./lotto:"+route+")"))
76 afterOwner = expected[0]["nextOwner"]
77 } else {
78 uassert.False(t, strings.Contains(result, "[Next]"))
79 last := expected[len(expected)-1]["owner"]
80 uassert.True(t, strings.Contains(Render("number?number=123&afterOwner="+url.QueryEscape(last)), "No owners on this page."))
81 }
82 }
83 uassert.Equal(t, holdings.Size(), 42)
84}
85