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/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/bazaar/bazaarv5

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
bazaarv5
Namespace
g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt / bazaar
Files
2 (gnomod.toml)
Exported functions
32
Module
gno.land/r/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/bazaar/bazaarv5
gno
0.9

Files (2)

  • gnomod.tomltoml
  • bazaarv5.gnogno
bazaarv5.gnogno
1package bazaarv523import (4	"chain"5	"chain/banker"6	"chain/runtime/unsafe"7	"strconv"8	"strings"910	"gno.land/p/nt/avl/v0"11)1213const (14	pkgPath          = "gno.land/r/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/bazaar/bazaarv5"15	nativeDenom      = "ugnot"16	defaultLaunchFee = int64(1_000_000_000) // 1000 GNOT17	maxNameLen       = 6418	maxImageLen      = 20019	maxSupplyBound   = 1_000_00020	maxRoyaltyBps    = 100021	maxSymbolLen     = 1122	maxSlugLen         = 1123	minSlugLen         = 224	defaultProtocolBps = int64(200) // 2% Magic Eden25	maxProtocolBps     = int64(500)26)2728type collection struct {29	slug       string30	name       string31	symbol     string32	cover      string33	pkg        string34	creator    address35	maxSupply  int36	mintPrice  int6437	minted     int38	royaltyBps int39}4041type reservation struct {42	who  address43	paid int6444}4546var (47	bySlug      avl.Tree48	byPkg       avl.Tree49	reserved    avl.Tree50	inited      bool51	admin         address52	self          address53	protocolSink  address54	launchFee        int6455	protocolBps      int6456	genesisPkg       string57	genesisSink      address58	genesisShareBps  int6459	discountPusher   string60	holderDisc       avl.Tree61)6263func Init(cur realm) {64	if inited {65		panic("factory: already initialized")66	}67	if !cur.Previous().IsUserCall() {68		panic("factory: EOA only")69	}70	admin = cur.Previous().Address()71	protocolSink = admin72	self = cur.Address()73	bySlug = avl.Tree{}74	byPkg = avl.Tree{}75	reserved = avl.Tree{}76	holderDisc = avl.Tree{}77	genesisPkg = ""78	genesisShareBps = 079	discountPusher = ""80	var z address81	genesisSink = z82	launchFee = defaultLaunchFee83	protocolBps = defaultProtocolBps84	inited = true85	chain.Emit("Init", "admin", admin.String())86}8788func Address() address {89	return chain.PackageAddress(pkgPath)90}9192func LaunchFee() int64 {93	requireInit()94	return launchFee95}9697func Admin() string {98	requireInit()99	return admin.String()100}101102func SetLaunchFee(cur realm, ugnot int64) {103	requireAdmin(cur)104	if ugnot < 0 {105		panic("factory: launch fee")106	}107	launchFee = ugnot108	chain.Emit("SetLaunchFee", "ugnot", strconv.FormatInt(ugnot, 10))109}110111func ProtocolBps() int64 {112	requireInit()113	if protocolBps <= 0 {114		return defaultProtocolBps115	}116	return protocolBps117}118119func SetProtocolBps(cur realm, bps int64) {120	requireAdmin(cur)121	if bps < 0 || bps > maxProtocolBps {122		panic("factory: protocol bps")123	}124	protocolBps = bps125	chain.Emit("SetProtocolBps", "bps", strconv.FormatInt(bps, 10))126}127128func ProtocolSink() address {129	requireInit()130	return protocolSink131}132133func SetProtocolSink(cur realm, next address) {134	requireAdmin(cur)135	if !next.IsValid() {136		panic("factory: invalid address")137	}138	if next == protocolSink {139		panic("factory: already sink")140	}141	protocolSink = next142	chain.Emit("SetProtocolSink", "addr", next.String())143}144145func GenesisPkg() string {146	requireInit()147	return genesisPkg148}149150func GenesisSink() address {151	requireInit()152	return genesisSink153}154155func GenesisShareBps() int64 {156	requireInit()157	if genesisPkg == "" {158		return 0159	}160	if genesisShareBps <= 0 {161		return 1100162	}163	return genesisShareBps164}165166func HolderDiscount(owner string) int64 {167	requireInit()168	if genesisPkg == "" {169		return 0170	}171	v := holderDisc.Get(strings.ToLower(strings.TrimSpace(owner)))172	if v == nil {173		return 0174	}175	return v.(int64)176}177178func AttachGenesis(cur realm) {179	requireInit()180	prev := cur.Previous()181	if !prev.IsCode() {182		panic("factory: genesis realm")183	}184	eoa := prev.Previous()185	if !eoa.IsUserCall() || eoa.Address() != admin {186		panic("factory: not admin")187	}188	pkg := prev.PkgPath()189	if pkg == "" {190		panic("factory: genesis pkg")191	}192	if genesisPkg != "" && genesisPkg != pkg {193		panic("factory: genesis set")194	}195	genesisPkg = pkg196	genesisSink = prev.Address()197	if genesisShareBps <= 0 {198		genesisShareBps = 1100199	}200	chain.Emit("AttachGenesis", "pkg", pkg)201}202203func SetGenesis(cur realm, pkg string) {204	requireAdmin(cur)205	pkg = strings.TrimSpace(pkg)206	if pkg == "" || !strings.HasPrefix(pkg, "gno.land/r/") {207		panic("factory: genesis pkg")208	}209	genesisPkg = pkg210	genesisSink = chain.PackageAddress(pkg)211	if genesisShareBps <= 0 {212		genesisShareBps = 1100213	}214	chain.Emit("SetGenesis", "pkg", pkg)215}216217func SetDiscountPusher(cur realm, pkg string) {218	requireAdmin(cur)219	pkg = strings.TrimSpace(pkg)220	if pkg == "" || !strings.HasPrefix(pkg, "gno.land/r/") {221		panic("factory: pusher pkg")222	}223	discountPusher = pkg224	chain.Emit("SetDiscountPusher", "pkg", pkg)225}226227func DiscountPusher() string {228	requireInit()229	return discountPusher230}231232func NoteHolderDiscount(cur realm, owner string, bps int64) {233	requireInit()234	prev := cur.Previous()235	if !prev.IsCode() {236		panic("factory: not genesis")237	}238	from := prev.PkgPath()239	ok := (genesisPkg != "" && from == genesisPkg) || (discountPusher != "" && from == discountPusher)240	if !ok {241		panic("factory: not genesis")242	}243	if bps < 0 {244		panic("factory: discount")245	}246	who := strings.ToLower(strings.TrimSpace(owner))247	if who == "" {248		panic("factory: owner")249	}250	if bps == 0 {251		holderDisc.Remove(who)252		return253	}254	holderDisc.Set(who, bps)255}256257func Register(cur realm, name, symbol, cover string, maxSupply int, mintPrice, royaltyBps int64) {258	requireInit()259	prev := cur.Previous()260	if !prev.IsCode() {261		panic("factory: collection realm")262	}263	creatorRlm := prev.Previous()264	if !creatorRlm.IsUserCall() {265		panic("factory: EOA creator")266	}267	pkg := prev.PkgPath()268	slug := lastElem(pkg)269	res := mustReserve(slug)270	if creatorRlm.Address() != res.who {271		panic("factory: reserved")272	}273	reserved.Remove(slug)274	register(pkg, creatorRlm.Address(), name, symbol, cover, maxSupply, mintPrice, royaltyBps)275}276277func Reserve(cur realm, slug string) {278	requireInit()279	if !cur.Previous().IsUserCall() {280		panic("factory: EOA only")281	}282	slug = strings.ToLower(strings.TrimSpace(slug))283	if !validSlug(slug) {284		panic("factory: slug")285	}286	if bySlug.Has(slug) || reserved.Has(slug) {287		panic("factory: slug taken")288	}289	caller := cur.Previous().Address()290	paid := reserveDue(caller)291	takeFactorySend(paid)292	reserved.Set(slug, &reservation{who: caller, paid: paid})293	chain.Emit("Reserve", "slug", slug, "paid", strconv.FormatInt(paid, 10))294}295296// ReserveDue is the ugnot Reserve will require from addr. The factory admin297// (the wallet that called Init) pays 0. Everyone else pays LaunchFee.298func ReserveDue(addr string) int64 {299	requireInit()300	who, ok := parseAddr(addr)301	if !ok {302		return launchFee303	}304	return reserveDue(who)305}306307func reserveDue(caller address) int64 {308	if caller == admin {309		return 0310	}311	return launchFee312}313314func parseAddr(raw string) (address, bool) {315	s := strings.TrimSpace(raw)316	if s == "" {317		var zero address318		return zero, false319	}320	who := address(s)321	if !who.IsValid() {322		var zero address323		return zero, false324	}325	return who, true326}327328func CancelReserve(cur realm, slug string) {329	requireInit()330	if !cur.Previous().IsUserCall() {331		panic("factory: EOA only")332	}333	slug = strings.ToLower(strings.TrimSpace(slug))334	res := mustReserve(slug)335	if res.who != cur.Previous().Address() {336		panic("factory: not reserver")337	}338	if bySlug.Has(slug) {339		panic("factory: already registered")340	}341	reserved.Remove(slug)342	if res.paid > 0 {343		bk := banker.NewBanker(banker.BankerTypeRealmSend, cur)344		bk.SendCoins(self, res.who, chain.Coins{{Denom: nativeDenom, Amount: res.paid}})345	}346	chain.Emit("CancelReserve", "slug", slug, "paid", strconv.FormatInt(res.paid, 10))347}348349func ReservedCreator(slug string) string {350	requireInit()351	slug = strings.ToLower(strings.TrimSpace(slug))352	if !reserved.Has(slug) {353		return ""354	}355	return reserved.Get(slug).(*reservation).who.String()356}357358func takeFactorySend(want int64) {359	sent := unsafe.OriginSend()360	if want == 0 {361		if len(sent) != 0 {362			panic("factory: extra denoms")363		}364		return365	}366	if len(sent) != 1 || sent[0].Denom != nativeDenom || sent[0].Amount != want {367		panic("factory: wrong payment")368	}369}370371func NoteMinted(cur realm, n int) {372	requireInit()373	if n < 0 {374		panic("factory: minted")375	}376	prev := cur.Previous()377	if !prev.IsCode() {378		panic("factory: collection realm")379	}380	c := mustByPkg(prev.PkgPath())381	c.minted = n382	byPkg.Set(c.pkg, c)383	bySlug.Set(c.slug, c)384}385386func NoteRoyalty(cur realm, bps int) {387	requireInit()388	if bps < 0 || bps > maxRoyaltyBps {389		panic("factory: royalty")390	}391	prev := cur.Previous()392	if !prev.IsCode() {393		panic("factory: collection realm")394	}395	c := mustByPkg(prev.PkgPath())396	c.royaltyBps = bps397	byPkg.Set(c.pkg, c)398	bySlug.Set(c.slug, c)399}400401func CollectionOf(slug string) string {402	requireInit()403	c := mustBySlug(slug)404	return c.pkg405}406407func CollectionAddr(slug string) string {408	requireInit()409	c := mustBySlug(slug)410	return chain.PackageAddress(c.pkg).String()411}412413func RoyaltyOf(slug string) int {414	requireInit()415	c := mustBySlug(slug)416	return c.royaltyBps417}418419func ListCollections() string {420	requireInit()421	out := ""422	bySlug.Iterate("", "", func(_ string, value any) bool {423		c := value.(*collection)424		if out != "" {425			out += "\n"426		}427		out += c.slug + "|" + c.name + "|" + c.cover + "|" + c.pkg + "|" + strconv.FormatInt(c.mintPrice, 10) + "|" + strconv.Itoa(c.maxSupply) + "|" + strconv.Itoa(c.minted) + "|" + c.creator.String() + "|" + chain.PackageAddress(c.pkg).String() + "|" + strconv.Itoa(c.royaltyBps)428		return false429	})430	return out431}432433func Withdraw(cur realm) {434	requireAdmin(cur)435	bk := banker.NewBanker(banker.BankerTypeRealmSend, cur)436	ugnot := bk.GetCoins(self).AmountOf(nativeDenom)437	locked := reservedPaid()438	avail := ugnot - locked439	if avail <= 0 {440		panic("factory: no funds")441	}442	bk.SendCoins(self, admin, chain.Coins{{Denom: nativeDenom, Amount: avail}})443	chain.Emit("Withdraw", "amount", strconv.FormatInt(avail, 10))444}445446func TransferAdmin(cur realm, next address) {447	requireAdmin(cur)448	if !next.IsValid() {449		panic("factory: invalid address")450	}451	if next == admin {452		panic("factory: already admin")453	}454	admin = next455	chain.Emit("TransferAdmin", "addr", next.String())456}457458func Render(_ string) string {459	if !inited {460		return "# Bazaar factory\n\nCall Init first.\n"461	}462	out := "# Bazaar factory\n\n"463	out += "- launch fee: " + strconv.FormatInt(launchFee, 10) + " ugnot\n"464	out += "- admin reserve: 0 ugnot\n"465	out += "- collections: " + strconv.Itoa(bySlug.Size()) + "\n\n"466	lines := ListCollections()467	if lines == "" {468		out += "_No collections._\n"469	} else {470		out += "```\n" + lines + "\n```\n"471	}472	return out473}474475func register(pkg string, creator address, name, symbol, cover string, maxSupply int, mintPrice, royaltyBps int64) {476	if !strings.HasPrefix(pkg, "gno.land/r/") {477		panic("factory: pkg")478	}479	slug := lastElem(pkg)480	if !validSlug(slug) {481		panic("factory: slug")482	}483	if !validName(name) {484		panic("factory: name")485	}486	if !validSymbol(symbol) {487		panic("factory: symbol")488	}489	if !validImage(cover) {490		panic("factory: cover")491	}492	if maxSupply < 0 || maxSupply > maxSupplyBound {493		panic("factory: maxSupply")494	}495	if mintPrice < 0 {496		panic("factory: mintPrice")497	}498	if royaltyBps < 0 || royaltyBps > maxRoyaltyBps {499		panic("factory: royalty")500	}501	if bySlug.Has(slug) {502		panic("factory: slug taken")503	}504	if byPkg.Has(pkg) {505		panic("factory: pkg already registered")506	}507	c := &collection{508		slug:       slug,509		name:       name,510		symbol:     symbol,511		cover:      cover,512		pkg:        pkg,513		creator:    creator,514		maxSupply:  maxSupply,515		mintPrice:  mintPrice,516		royaltyBps: int(royaltyBps),517	}518	bySlug.Set(slug, c)519	byPkg.Set(pkg, c)520	chain.Emit("Register", "slug", slug, "pkg", pkg, "creator", creator.String())521}522523func requireInit() {524	if !inited {525		panic("factory: call Init first")526	}527}528529func requireAdmin(cur realm) {530	requireInit()531	if !cur.Previous().IsUserCall() {532		panic("factory: EOA only")533	}534	if cur.Previous().Address() != admin {535		panic("factory: not admin")536	}537}538539func mustReserve(slug string) *reservation {540	v := reserved.Get(slug)541	if v == nil {542		panic("factory: not reserved")543	}544	return v.(*reservation)545}546547func reservedPaid() int64 {548	var n int64549	reserved.Iterate("", "", func(_ string, value any) bool {550		n += value.(*reservation).paid551		return false552	})553	return n554}555556func mustBySlug(slug string) *collection {557	v := bySlug.Get(slug)558	if v == nil {559		panic("factory: unknown collection")560	}561	return v.(*collection)562}563564func mustByPkg(pkg string) *collection {565	v := byPkg.Get(pkg)566	if v == nil {567		panic("factory: unknown collection")568	}569	return v.(*collection)570}571572func lastElem(pkg string) string {573	i := strings.LastIndex(pkg, "/")574	if i < 0 || i+1 >= len(pkg) {575		panic("factory: pkg")576	}577	return pkg[i+1:]578}579580func validSlug(s string) bool {581	if len(s) < minSlugLen || len(s) > maxSlugLen {582		return false583	}584	if s[0] < 'a' || s[0] > 'z' {585		return false586	}587	return asciiSet(s, "abcdefghijklmnopqrstuvwxyz0123456789")588}589590func validSymbol(s string) bool {591	if len(s) < 1 || len(s) > maxSymbolLen {592		return false593	}594	return asciiSet(s, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-")595}596597func validName(name string) bool {598	if len(name) < 1 || len(name) > maxNameLen {599		return false600	}601	return !strings.ContainsAny(name, "\n\r|")602}603604func validImage(u string) bool {605	if u == "" {606		return true607	}608	if len(u) > maxImageLen {609		return false610	}611	if strings.ContainsAny(u, " \t\n\r|<>\"'`") {612		return false613	}614	if strings.HasPrefix(u, "https://") || strings.HasPrefix(u, "http://") {615		return true616	}617	const prefix = "/samples/"618	if !strings.HasPrefix(u, prefix) {619		return false620	}621	rest := u[len(prefix):]622	if rest == "" {623		return false624	}625	return asciiSet(rest, "abcdefghijklmnopqrstuvwxyz0123456789._-")626}627628func asciiSet(s, allowed string) bool {629	for i := 0; i < len(s); i++ {630		if !strings.ContainsRune(allowed, rune(s[i])) {631			return false632		}633	}634	return true635}636

Functions

  • Address() string

  • Admin() string

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

  • CancelReserve(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)

  • CollectionAddr(slug string) string

  • CollectionOf(slug string) string

  • DiscountPusher() string

  • GenesisPkg() string

  • GenesisShareBps() int64

  • GenesisSink() string

  • HolderDiscount(owner string) int64

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

  • LaunchFee() int64

  • ListCollections() string

  • NoteHolderDiscount(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, bps int64)

  • NoteMinted(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}, n int)

  • NoteRoyalty(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}, bps int)

  • ProtocolBps() int64

  • ProtocolSink() string

  • Register(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, symbol string, cover string, maxSupply int, mintPrice int64, royaltyBps int64)

  • Render(string) string

  • Reserve(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)

  • ReservedCreator(slug string) string

  • ReserveDue(addr string) int64

  • RoyaltyOf(slug string) int

  • SetDiscountPusher(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}, pkg string)

  • SetGenesis(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}, pkg string)

  • SetLaunchFee(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}, ugnot int64)

  • SetProtocolBps(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}, bps int64)

  • SetProtocolSink(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}, next string)

  • TransferAdmin(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}, next string)

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

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.