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/meta

Realm
Open in gnoweb ↗

Overview

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

Files (2)

  • gnomod.tomltoml
  • meta.gnogno
meta.gnogno
1// Package meta stores off-pad token presentation data (description, image, socials).2// Independent of pad versions — upgrade without redeploying markets.3//4// Key = padPkg + "|" + launchId5// First SetMeta caller becomes owner; only owner may update later.6package meta78import (9	"chain"10	"chain/runtime"11	"strconv"12	"strings"1314	"gno.land/p/nt/avl/v0"15)1617const (18	maxDescLen    = 50019	maxURILen     = 20020	maxHandleLen  = 6421	maxPadPathLen = 20022	maxLaunchId   = 3223)2425// TokenMeta is presentation data for one launch (not trading state).26type TokenMeta struct {27	PadPkg      string28	LaunchID    string29	Owner       address30	Description string31	ImageURI    string32	Website     string33	Twitter     string34	Telegram    string35	Updated     int6436}3738var (39	// byKey: pad|id -> *TokenMeta40	byKey  avl.Tree41	inited bool42)4344func Init(cur realm) {45	if inited {46		panic("meta: already initialized")47	}48	if !cur.Previous().IsUserCall() {49		panic("meta: EOA only")50	}51	inited = true52	byKey = avl.Tree{}53	chain.Emit("Init", "by", cur.Previous().Address().String())54}5556func ensure() {57	if !inited {58		byKey = avl.Tree{}59		inited = true60	}61}6263func makeKey(padPkg, launchID string) string {64	return padPkg + "|" + launchID65}6667func sanitizeText(s string, max int) string {68	s = strings.TrimSpace(s)69	if len(s) > max {70		s = s[:max]71	}72	out := ""73	for _, c := range s {74		if c >= 0x20 && c != 0x7f {75			out += string(c)76		}77	}78	return out79}8081func validateURI(uri string) {82	if uri == "" {83		return84	}85	if !(strings.HasPrefix(uri, "https://") || strings.HasPrefix(uri, "http://") || strings.HasPrefix(uri, "ipfs://")) {86		panic("meta: uri must be http(s) or ipfs")87	}88}8990func validatePadPkg(padPkg string) {91	padPkg = strings.TrimSpace(padPkg)92	if padPkg == "" || len(padPkg) > maxPadPathLen {93		panic("meta: invalid pad path")94	}95	if !strings.HasPrefix(padPkg, "gno.land/r/") {96		panic("meta: pad must be gno.land/r/…")97	}98}99100// SetMeta upserts metadata for a launch. First writer owns the entry.101func SetMeta(cur realm, padPkg, launchID, description, imageURI, website, twitter, telegram string) {102	if !cur.Previous().IsUserCall() {103		panic("meta: EOA only")104	}105	ensure()106	validatePadPkg(padPkg)107	launchID = sanitizeText(launchID, maxLaunchId)108	if launchID == "" {109		panic("meta: launch id required")110	}111	description = sanitizeText(description, maxDescLen)112	imageURI = sanitizeText(imageURI, maxURILen)113	website = sanitizeText(website, maxURILen)114	twitter = sanitizeText(twitter, maxHandleLen)115	telegram = sanitizeText(telegram, maxHandleLen)116	validateURI(imageURI)117	validateURI(website)118119	key := makeKey(padPkg, launchID)120	caller := cur.Previous().Address()121	existing := byKey.Get(key)122	if existing != nil {123		tm := existing.(*TokenMeta)124		if tm.Owner != caller {125			panic("meta: not owner")126		}127		tm.Description = description128		tm.ImageURI = imageURI129		tm.Website = website130		tm.Twitter = twitter131		tm.Telegram = telegram132		tm.Updated = runtime.ChainHeight()133		byKey.Set(key, tm)134	} else {135		tm := &TokenMeta{136			PadPkg:      padPkg,137			LaunchID:    launchID,138			Owner:       caller,139			Description: description,140			ImageURI:    imageURI,141			Website:     website,142			Twitter:     twitter,143			Telegram:    telegram,144			Updated:     runtime.ChainHeight(),145		}146		byKey.Set(key, tm)147	}148	chain.Emit("SetMeta", "key", key, "owner", caller.String())149}150151// GetMeta returns:152//153//	owner|description|imageURI|website|twitter|telegram|updated154//155// Empty string if none.156func GetMeta(padPkg, launchID string) string {157	ensure()158	key := makeKey(strings.TrimSpace(padPkg), strings.TrimSpace(launchID))159	v := byKey.Get(key)160	if v == nil {161		return ""162	}163	tm := v.(*TokenMeta)164	return tm.Owner.String() + "|" +165		tm.Description + "|" +166		tm.ImageURI + "|" +167		tm.Website + "|" +168		tm.Twitter + "|" +169		tm.Telegram + "|" +170		strconv.FormatInt(tm.Updated, 10)171}172173// HasMeta reports whether metadata exists.174func HasMeta(padPkg, launchID string) bool {175	ensure()176	return byKey.Has(makeKey(strings.TrimSpace(padPkg), strings.TrimSpace(launchID)))177}178179// MetaCount returns number of entries.180func MetaCount() int {181	ensure()182	return byKey.Size()183}184185// ClearMeta removes caller's owned entry.186func ClearMeta(cur realm, padPkg, launchID string) {187	if !cur.Previous().IsUserCall() {188		panic("meta: EOA only")189	}190	ensure()191	key := makeKey(strings.TrimSpace(padPkg), strings.TrimSpace(launchID))192	v := byKey.Get(key)193	if v == nil {194		return195	}196	tm := v.(*TokenMeta)197	if tm.Owner != cur.Previous().Address() {198		panic("meta: not owner")199	}200	byKey.Remove(key)201	chain.Emit("ClearMeta", "key", key)202}203204func sanitizeMD(s string) string {205	s = strings.ReplaceAll(s, "`", "'")206	s = strings.ReplaceAll(s, "<", "")207	s = strings.ReplaceAll(s, ">", "")208	return s209}210211func Render(path string) string {212	path = strings.Trim(path, "/")213	ensure()214	if path == "" {215		return "# gnomi meta\n\n- Entries: **" + strconv.Itoa(byKey.Size()) + "**\n\n" +216			"SetMeta(padPkg, launchID, description, imageURI, website, twitter, telegram)\n"217	}218	return "> [!WARNING]\n> Path not found: " + sanitizeMD(path) + "\n"219}220221func resetForTest() {222	byKey = avl.Tree{}223	inited = false224}225

Functions

  • ClearMeta(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}, padPkg string, launchID string)

  • GetMeta(padPkg string, launchID string) string

  • HasMeta(padPkg string, launchID string) bool

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

  • MetaCount() int

  • Render(path string) string

  • SetMeta(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}, padPkg string, launchID string, description string, imageURI string, website string, twitter string, telegram 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.