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

Realm
Open in gnoweb ↗

Overview

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

Files (2)

  • gnomod.tomltoml
  • bazaarv2.gnogno
bazaarv2.gnogno
1package bazaarv223import (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/bazaarv2"15	nativeDenom      = "ugnot"16	defaultLaunchFee = int64(10_000_000) // 10 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	launchFee   int6454	protocolBps int6455)5657func Init(cur realm) {58	if inited {59		panic("factory: already initialized")60	}61	if !cur.Previous().IsUserCall() {62		panic("factory: EOA only")63	}64	admin = cur.Previous().Address()65	self = cur.Address()66	bySlug = avl.Tree{}67	byPkg = avl.Tree{}68	reserved = avl.Tree{}69	launchFee = defaultLaunchFee70	protocolBps = defaultProtocolBps71	inited = true72	chain.Emit("Init", "admin", admin.String())73}7475func Address() address {76	return chain.PackageAddress(pkgPath)77}7879func LaunchFee() int64 {80	requireInit()81	return launchFee82}8384func Admin() string {85	requireInit()86	return admin.String()87}8889func SetLaunchFee(cur realm, ugnot int64) {90	requireAdmin(cur)91	if ugnot < 0 {92		panic("factory: launch fee")93	}94	launchFee = ugnot95	chain.Emit("SetLaunchFee", "ugnot", strconv.FormatInt(ugnot, 10))96}9798func ProtocolBps() int64 {99	requireInit()100	if protocolBps <= 0 {101		return defaultProtocolBps102	}103	return protocolBps104}105106func SetProtocolBps(cur realm, bps int64) {107	requireAdmin(cur)108	if bps < 0 || bps > maxProtocolBps {109		panic("factory: protocol bps")110	}111	protocolBps = bps112	chain.Emit("SetProtocolBps", "bps", strconv.FormatInt(bps, 10))113}114115func Register(cur realm, name, symbol, cover string, maxSupply int, mintPrice, royaltyBps int64) {116	requireInit()117	prev := cur.Previous()118	if !prev.IsCode() {119		panic("factory: collection realm")120	}121	creatorRlm := prev.Previous()122	if !creatorRlm.IsUserCall() {123		panic("factory: EOA creator")124	}125	pkg := prev.PkgPath()126	slug := lastElem(pkg)127	res := mustReserve(slug)128	if creatorRlm.Address() != res.who {129		panic("factory: reserved")130	}131	reserved.Remove(slug)132	register(pkg, creatorRlm.Address(), name, symbol, cover, maxSupply, mintPrice, royaltyBps)133}134135func Reserve(cur realm, slug string) {136	requireInit()137	if !cur.Previous().IsUserCall() {138		panic("factory: EOA only")139	}140	slug = strings.ToLower(strings.TrimSpace(slug))141	if !validSlug(slug) {142		panic("factory: slug")143	}144	if bySlug.Has(slug) || reserved.Has(slug) {145		panic("factory: slug taken")146	}147	paid := launchFee148	takeFactorySend(paid)149	reserved.Set(slug, &reservation{who: cur.Previous().Address(), paid: paid})150	chain.Emit("Reserve", "slug", slug, "paid", strconv.FormatInt(paid, 10))151}152153func CancelReserve(cur realm, slug string) {154	requireInit()155	if !cur.Previous().IsUserCall() {156		panic("factory: EOA only")157	}158	slug = strings.ToLower(strings.TrimSpace(slug))159	res := mustReserve(slug)160	if res.who != cur.Previous().Address() {161		panic("factory: not reserver")162	}163	if bySlug.Has(slug) {164		panic("factory: already registered")165	}166	reserved.Remove(slug)167	if res.paid > 0 {168		bk := banker.NewBanker(banker.BankerTypeRealmSend, cur)169		bk.SendCoins(self, res.who, chain.Coins{{Denom: nativeDenom, Amount: res.paid}})170	}171	chain.Emit("CancelReserve", "slug", slug, "paid", strconv.FormatInt(res.paid, 10))172}173174func ReservedCreator(slug string) string {175	requireInit()176	slug = strings.ToLower(strings.TrimSpace(slug))177	if !reserved.Has(slug) {178		return ""179	}180	return reserved.Get(slug).(*reservation).who.String()181}182183func takeFactorySend(want int64) {184	sent := unsafe.OriginSend()185	if want == 0 {186		if len(sent) != 0 {187			panic("factory: extra denoms")188		}189		return190	}191	if len(sent) != 1 || sent[0].Denom != nativeDenom || sent[0].Amount != want {192		panic("factory: wrong payment")193	}194}195196func NoteMinted(cur realm, n int) {197	requireInit()198	if n < 0 {199		panic("factory: minted")200	}201	prev := cur.Previous()202	if !prev.IsCode() {203		panic("factory: collection realm")204	}205	c := mustByPkg(prev.PkgPath())206	c.minted = n207	byPkg.Set(c.pkg, c)208	bySlug.Set(c.slug, c)209}210211func NoteRoyalty(cur realm, bps int) {212	requireInit()213	if bps < 0 || bps > maxRoyaltyBps {214		panic("factory: royalty")215	}216	prev := cur.Previous()217	if !prev.IsCode() {218		panic("factory: collection realm")219	}220	c := mustByPkg(prev.PkgPath())221	c.royaltyBps = bps222	byPkg.Set(c.pkg, c)223	bySlug.Set(c.slug, c)224}225226func CollectionOf(slug string) string {227	requireInit()228	c := mustBySlug(slug)229	return c.pkg230}231232func CollectionAddr(slug string) string {233	requireInit()234	c := mustBySlug(slug)235	return chain.PackageAddress(c.pkg).String()236}237238func RoyaltyOf(slug string) int {239	requireInit()240	c := mustBySlug(slug)241	return c.royaltyBps242}243244func ListCollections() string {245	requireInit()246	out := ""247	bySlug.Iterate("", "", func(_ string, value any) bool {248		c := value.(*collection)249		if out != "" {250			out += "\n"251		}252		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)253		return false254	})255	return out256}257258func Withdraw(cur realm) {259	requireAdmin(cur)260	bk := banker.NewBanker(banker.BankerTypeRealmSend, cur)261	ugnot := bk.GetCoins(self).AmountOf(nativeDenom)262	locked := reservedPaid()263	avail := ugnot - locked264	if avail <= 0 {265		panic("factory: no funds")266	}267	bk.SendCoins(self, admin, chain.Coins{{Denom: nativeDenom, Amount: avail}})268	chain.Emit("Withdraw", "amount", strconv.FormatInt(avail, 10))269}270271func TransferAdmin(cur realm, next address) {272	requireAdmin(cur)273	if !next.IsValid() {274		panic("factory: invalid address")275	}276	if next == admin {277		panic("factory: already admin")278	}279	admin = next280	chain.Emit("TransferAdmin", "addr", next.String())281}282283func Render(_ string) string {284	if !inited {285		return "# Bazaar factory\n\nCall Init first.\n"286	}287	out := "# Bazaar factory\n\n"288	out += "- launch fee: " + strconv.FormatInt(launchFee, 10) + " ugnot\n"289	out += "- collections: " + strconv.Itoa(bySlug.Size()) + "\n\n"290	lines := ListCollections()291	if lines == "" {292		out += "_No collections._\n"293	} else {294		out += "```\n" + lines + "\n```\n"295	}296	return out297}298299func register(pkg string, creator address, name, symbol, cover string, maxSupply int, mintPrice, royaltyBps int64) {300	if !strings.HasPrefix(pkg, "gno.land/r/") {301		panic("factory: pkg")302	}303	slug := lastElem(pkg)304	if !validSlug(slug) {305		panic("factory: slug")306	}307	if !validName(name) {308		panic("factory: name")309	}310	if !validSymbol(symbol) {311		panic("factory: symbol")312	}313	if !validImage(cover) {314		panic("factory: cover")315	}316	if maxSupply < 0 || maxSupply > maxSupplyBound {317		panic("factory: maxSupply")318	}319	if mintPrice < 0 {320		panic("factory: mintPrice")321	}322	if royaltyBps < 0 || royaltyBps > maxRoyaltyBps {323		panic("factory: royalty")324	}325	if bySlug.Has(slug) {326		panic("factory: slug taken")327	}328	if byPkg.Has(pkg) {329		panic("factory: pkg already registered")330	}331	c := &collection{332		slug:       slug,333		name:       name,334		symbol:     symbol,335		cover:      cover,336		pkg:        pkg,337		creator:    creator,338		maxSupply:  maxSupply,339		mintPrice:  mintPrice,340		royaltyBps: int(royaltyBps),341	}342	bySlug.Set(slug, c)343	byPkg.Set(pkg, c)344	chain.Emit("Register", "slug", slug, "pkg", pkg, "creator", creator.String())345}346347func requireInit() {348	if !inited {349		panic("factory: call Init first")350	}351}352353func requireAdmin(cur realm) {354	requireInit()355	if !cur.Previous().IsUserCall() {356		panic("factory: EOA only")357	}358	if cur.Previous().Address() != admin {359		panic("factory: not admin")360	}361}362363func mustReserve(slug string) *reservation {364	v := reserved.Get(slug)365	if v == nil {366		panic("factory: not reserved")367	}368	return v.(*reservation)369}370371func reservedPaid() int64 {372	var n int64373	reserved.Iterate("", "", func(_ string, value any) bool {374		n += value.(*reservation).paid375		return false376	})377	return n378}379380func mustBySlug(slug string) *collection {381	v := bySlug.Get(slug)382	if v == nil {383		panic("factory: unknown collection")384	}385	return v.(*collection)386}387388func mustByPkg(pkg string) *collection {389	v := byPkg.Get(pkg)390	if v == nil {391		panic("factory: unknown collection")392	}393	return v.(*collection)394}395396func lastElem(pkg string) string {397	i := strings.LastIndex(pkg, "/")398	if i < 0 || i+1 >= len(pkg) {399		panic("factory: pkg")400	}401	return pkg[i+1:]402}403404func validSlug(s string) bool {405	if len(s) < minSlugLen || len(s) > maxSlugLen {406		return false407	}408	if s[0] < 'a' || s[0] > 'z' {409		return false410	}411	return asciiSet(s, "abcdefghijklmnopqrstuvwxyz0123456789")412}413414func validSymbol(s string) bool {415	if len(s) < 1 || len(s) > maxSymbolLen {416		return false417	}418	return asciiSet(s, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-")419}420421func validName(name string) bool {422	if len(name) < 1 || len(name) > maxNameLen {423		return false424	}425	return !strings.ContainsAny(name, "\n\r|")426}427428func validImage(u string) bool {429	if u == "" {430		return true431	}432	if len(u) > maxImageLen {433		return false434	}435	if strings.ContainsAny(u, " \t\n\r|<>\"'`") {436		return false437	}438	if strings.HasPrefix(u, "https://") || strings.HasPrefix(u, "http://") {439		return true440	}441	const prefix = "/samples/"442	if !strings.HasPrefix(u, prefix) {443		return false444	}445	rest := u[len(prefix):]446	if rest == "" {447		return false448	}449	return asciiSet(rest, "abcdefghijklmnopqrstuvwxyz0123456789._-")450}451452func asciiSet(s, allowed string) bool {453	for i := 0; i < len(s); i++ {454		if !strings.ContainsRune(allowed, rune(s[i])) {455			return false456		}457	}458	return true459}460

Functions

  • Address() string

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

  • 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

  • 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

  • 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

  • RoyaltyOf(slug string) int

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

  • 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.