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/g1747t5m2f08plqjlrjk2q0qld7465hxz8gkx59c/home

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
home
Namespace
g1747t5m2f08plqjlrjk2q0qld7465hxz8gkx59c
Files
7 (gnomod.toml)
Exported functions
11
Module
gno.land/r/g1747t5m2f08plqjlrjk2q0qld7465hxz8gkx59c/home
gno
0.9

Files (7)

  • gnomod.tomltoml
  • banner.gnogno
  • content.gnogno
  • gallery.gnogno
  • home.gnogno
  • render.gnogno
  • home_test.gnogno
home.gnogno
1// Package home is zôÖma's profile page on gno.land.2//3// gnoweb renders a profile by calling Render("") on the realm at exactly4// /r/<namespace>/home, so this path carries no /vN suffix.5//6// The page is assembled from SLOTS: named markdown fragments, one Set7// transaction each. The slot named "layout" is the template; every :slug:

Functions

  • Append(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}, slug string, body string)

  • Delete(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}, slug string)

  • DeleteGallery(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}, name string)

  • Get(slug string) string

  • HasHeart(addr string) bool

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

  • Hearts() int

  • Render(path string) string

  • Revision() int

  • Set(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}, slug string, body string)

  • SetGallery(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}, name string, spec string)

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

Rendered

RenderedRawgnoweb ↗
8// placeholder in it is replaced by the slot of that name, in a single pass.
9// init seeds every slot from content.gno, so the page is complete the block
10// it goes live and later edits are data, not redeploys.
11//
12// One thing on this page is not written by its owner: visitors can send a
13// heart (<3), one per address, and the page counts them.
14package home
15
16import (
17 "strconv"
18 "strings"
19
20 "chain/runtime"
21
22 "gno.land/p/nt/avl/v0"
23)
24
25// admin is the only address allowed to edit slots.
26const admin = address("g1747t5m2f08plqjlrjk2q0qld7465hxz8gkx59c")
27
28const (
29 layoutSlug = "layout"
30 maxSlugLen = 64
31 maxRecent = 7
32)
33
34type slot struct {
35 body string
36 rev int
37 updated int64
38}
39
40var (
41 slots = avl.NewTree() // slug -> *slot
42 rev int // total slot writes
43
44 hearts = avl.NewTree() // address string -> int64 height of the heart
45 recent []address // newest first, at most maxRecent
46)
47
48// reservedSlugs are placeholders computed at render time. A slot may not take
49// one of these names, so nothing a slot says can shadow chain state.
50var reservedSlugs = []string{"chainid", "height", "hearts", "hero", "realm", "rev"}
51
52func init() {
53 for _, s := range defaultSlots {
54 rev++
55 slots.Set(s.slug, &slot{body: s.body, rev: rev, updated: runtime.ChainHeight()})
56 }
57 for _, g := range defaultGalleries {
58 galleries.Set(g.name, parseGallery(g.spec))
59 }
60}
61
62func assertAdmin(cur realm) {
63 if cur.Previous().Address() != admin {
64 panic("restricted to admin")
65 }
66}
67
68func validSlug(slug string) bool {
69 if len(slug) == 0 || len(slug) > maxSlugLen {
70 return false
71 }
72 for i := 0; i < len(slug); i++ {
73 c := slug[i]
74 if !(c >= 'a' && c <= 'z' || c >= '0' && c <= '9' || c == '-' || c == '_' || c == '.') {
75 return false
76 }
77 }
78 return true
79}
80
81func assertWritableSlug(slug string) {
82 if !validSlug(slug) {
83 panic("invalid slug: want 1-" + strconv.Itoa(maxSlugLen) + " bytes of [a-z0-9._-], got " + strconv.Quote(slug))
84 }
85 for _, r := range reservedSlugs {
86 if slug == r {
87 panic("reserved slug: " + slug)
88 }
89 }
90 if strings.HasPrefix(slug, galleryPrefix) {
91 panic("reserved slug: " + galleryPrefix + "* renders a gallery, use SetGallery")
92 }
93}
94
95// Set creates or replaces one slot.
96func Set(cur realm, slug, body string) {
97 assertAdmin(cur)
98 assertWritableSlug(slug)
99 rev++
100 slots.Set(slug, &slot{body: body, rev: rev, updated: runtime.ChainHeight()})
101}
102
103// Append adds to the end of a slot, creating it when absent, for bodies too
104// large for one transaction.
105func Append(cur realm, slug, body string) {
106 assertAdmin(cur)
107 assertWritableSlug(slug)
108 prev := ""
109 if v := slots.Get(slug); v != nil {
110 prev = v.(*slot).body
111 }
112 rev++
113 slots.Set(slug, &slot{body: prev + body, rev: rev, updated: runtime.ChainHeight()})
114}
115
116// Delete removes a slot. Deleting "layout" falls back to the built-in layout.
117func Delete(cur realm, slug string) {
118 assertAdmin(cur)
119 if _, removed := slots.Remove(slug); !removed {
120 panic("no such slot: " + slug)
121 }
122 rev++
123}
124
125// Get returns a slot body, or "" when the slot does not exist.
126func Get(slug string) string {
127 if v := slots.Get(slug); v != nil {
128 return v.(*slot).body
129 }
130 return ""
131}
132
133// Revision is the total number of slot writes accepted.
134func Revision() int { return rev }
135
136// Heart records one <3 from the caller. Each address can send exactly one.
137func Heart(cur realm) {
138 from := cur.Previous().Address()
139 if hearts.Has(from.String()) {
140 panic("already sent: one <3 per address")
141 }
142 hearts.Set(from.String(), runtime.ChainHeight())
143
144 recent = append([]address{from}, recent...)
145 if len(recent) > maxRecent {
146 recent = recent[:maxRecent]
147 }
148}
149
150// Hearts returns how many distinct addresses sent a <3.
151func Hearts() int { return hearts.Size() }
152
153// HasHeart reports whether addr already sent a <3.
154func HasHeart(addr address) bool { return hearts.Has(addr.String()) }
155

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.