PathrockNetwork Gno Explorer
HomeBlocksTransactionsRealmsPackagesValidators

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/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/gnomi/hubv2

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
hubv2
Namespace
g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt / gnomi
Files
2 (gnomod.toml)
Exported functions
13
Module
gno.land/r/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/gnomi/hubv2
gno
0.9

Files (2)

  • gnomod.tomltoml
  • hub.gnogno
hub.gnogno
1// Package hubv2 is the multi-admin module router for gnomemepad (Phase 3F).2//3// Diff vs hub v1:4//   - Multiple admins (AddAdmin / RemoveAdmin / ListAdmins)5//   - Any admin may SetModule / TransferAdmin rights via AddAdmin6//   - Ops helpers: AdminCount, IsAdmin7//8// Migrate: deploy hubv2 → re-SetModule all paths → point UI HUB=hubv29package hubv21011import (12	"chain"13	"strconv"14	"strings"1516	"gno.land/p/nt/avl/v0"17)1819var (20	// admins: address string -> true21	admins avl.Tree22	inited bool23	// modules: name -> package path string24	modules avl.Tree25)2627// Init sets the first admin (deployer EOA). Call once.28func Init(cur realm) {29	if inited {30		panic("hubv2: already initialized")31	}32	if !cur.Previous().IsUserCall() {33		panic("hubv2: EOA only")34	}35	a := cur.Previous().Address()36	admins = avl.Tree{}37	modules = avl.Tree{}38	admins.Set(a.String(), true)39	inited = true40	chain.Emit("Init", "admin", a.String())41}4243func requireInit() {44	if !inited {45		panic("hubv2: call Init first")46	}47}4849func isAdminAddr(addr address) bool {50	return admins.Has(addr.String())51}5253func requireAdmin(cur realm) {54	requireInit()55	if !cur.Previous().IsUserCall() {56		panic("hubv2: EOA only")57	}58	if !isAdminAddr(cur.Previous().Address()) {59		panic("hubv2: not admin")60	}61}6263// IsAdmin reports whether addr is an admin.64func IsAdmin(addr string) bool {65	requireInit()66	return admins.Has(strings.TrimSpace(addr))67}6869// AdminCount returns number of admins.70func AdminCount() int {71	requireInit()72	return admins.Size()73}7475// ListAdmins returns newline-separated admin addresses.76func ListAdmins() string {77	requireInit()78	out := ""79	admins.Iterate("", "", func(key string, _ any) bool {80		if out != "" {81			out += "\n"82		}83		out += key84		return false85	})86	return out87}8889// AddAdmin grants admin rights (existing admin only).90func AddAdmin(cur realm, newAdmin address) {91	requireAdmin(cur)92	if !newAdmin.IsValid() {93		panic("hubv2: invalid address")94	}95	if isAdminAddr(newAdmin) {96		panic("hubv2: already admin")97	}98	admins.Set(newAdmin.String(), true)99	chain.Emit("AddAdmin", "addr", newAdmin.String())100}101102// RemoveAdmin revokes admin. Cannot remove last admin.103func RemoveAdmin(cur realm, who address) {104	requireAdmin(cur)105	if !who.IsValid() {106		panic("hubv2: invalid address")107	}108	if !isAdminAddr(who) {109		panic("hubv2: not an admin")110	}111	if admins.Size() <= 1 {112		panic("hubv2: cannot remove last admin")113	}114	// Prevent lock-out of caller if they're removing themselves as sole remaining — already size>1115	admins.Remove(who.String())116	chain.Emit("RemoveAdmin", "addr", who.String())117}118119// SetModule registers or updates a module path (any admin).120func SetModule(cur realm, name, path string) {121	requireAdmin(cur)122	name = strings.TrimSpace(name)123	path = strings.TrimSpace(path)124	if name == "" || len(name) > 32 {125		panic("hubv2: invalid name")126	}127	if path == "" || len(path) > 200 {128		panic("hubv2: invalid path")129	}130	if !strings.HasPrefix(path, "gno.land/") {131		panic("hubv2: path must start with gno.land/")132	}133	for _, c := range name {134		if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-') {135			panic("hubv2: name charset")136		}137	}138	modules.Set(name, path)139	chain.Emit("SetModule", "name", name, "path", path)140}141142// GetModule returns the package path for name, or "".143func GetModule(name string) string {144	requireInit()145	v := modules.Get(name)146	if v == nil {147		return ""148	}149	s, ok := v.(string)150	if !ok {151		return ""152	}153	return s154}155156// ListModules returns newline-separated "name|path".157func ListModules() string {158	requireInit()159	out := ""160	modules.Iterate("", "", func(key string, value any) bool {161		path, _ := value.(string)162		if out != "" {163			out += "\n"164		}165		out += key + "|" + path166		return false167	})168	return out169}170171// ModuleCount for ops.172func ModuleCount() int {173	requireInit()174	return modules.Size()175}176177// Inited reports Init.178func Inited() bool {179	return inited180}181182// Admin returns first admin (compat) — first key in tree iteration order.183func Admin() string {184	requireInit()185	out := ""186	admins.Iterate("", "", func(key string, _ any) bool {187		out = key188		return true189	})190	return out191}192193func Render(path string) string {194	path = strings.Trim(path, "/")195	if !inited {196		return "# gnomi hubv2\n\n> Not initialized.\n"197	}198	out := "# gnomi hubv2 (multi-admin)\n\n"199	out += "- Admins: **" + strconv.Itoa(admins.Size()) + "**\n"200	out += "- Modules: **" + strconv.Itoa(modules.Size()) + "**\n\n"201	out += "## Admins\n\n"202	admins.Iterate("", "", func(key string, _ any) bool {203		out += "- `" + key + "`\n"204		return false205	})206	out += "\n## Modules\n\n"207	modules.Iterate("", "", func(key string, value any) bool {208		p, _ := value.(string)209		out += "- **" + key + "**: `" + p + "`\n"210		return false211	})212	out += "\n## API\n\n- SetModule / GetModule / ListModules\n- AddAdmin / RemoveAdmin / ListAdmins / IsAdmin\n"213	_ = path214	return out215}216217func resetForTest() {218	admins = avl.Tree{}219	modules = avl.Tree{}220	inited = false221}222

Functions

  • AddAdmin(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}, newAdmin string)

  • Admin() string

  • AdminCount() int

  • GetModule(name string) string

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

  • Inited() bool

  • IsAdmin(addr string) bool

  • ListAdmins() string

  • ListModules() string

  • ModuleCount() int

  • RemoveAdmin(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}, who string)

  • Render(path string) string

  • SetModule(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, path 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.