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/g1nmqhha0ua730vejxqhrelldm4pga5j5ptle5ea/guardians_store_v1

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
guardians_store_v1
Namespace
g1nmqhha0ua730vejxqhrelldm4pga5j5ptle5ea
Files
2 (gnomod.toml)
Exported functions
17
Module
gno.land/r/g1nmqhha0ua730vejxqhrelldm4pga5j5ptle5ea/guardians_store_v1
gno
0.9

Files (2)

  • gnomod.tomltoml
  • store.gnogno
store.gnogno
1package guardians_store_v123// UNDEPLOYED. Selected inventory only; no minting or operator-transfer rights.4import (5	"chain"6	"chain/banker"7	"chain/runtime/unsafe"8	"strconv"9	"strings"1011	guardians "gno.land/r/g1nmqhha0ua730vejxqhrelldm4pga5j5ptle5ea/guardians"12)1314const Seller address = "g1a72vne647vcw9uv0gy7wn8sw8ffc66agl4jdr3"15const RoyaltyReceiver address = "g1lp547ww848djw0ammpqswegg7tc6xczqqtx07n"16const RoyaltyBps = int64(400)17const maxPrice = int64(9000000000000000) // multiplication by 400 stays in int641819type order struct {20	nonce  int6421	price  int6422	active bool23}2425var orders = make(map[string]*order)26var nextNonce int6427var storeAddress address28var paused = true2930func init(cur realm)   { storeAddress = cur.Address() }31func Address() address { return storeAddress }32func Version() string  { return "guardians.selected-store.v1" }33func Paused() bool     { return paused }34func NextNonce() int64 { return nextNonce + 1 }35func Identity() string {36	return `{"version":"` + Version() + `","seller":"` + Seller.String() + `","royaltyReceiver":"` + RoyaltyReceiver.String() + `","royaltyBps":400,"address":"` + storeAddress.String() + `","paused":` + strconv.FormatBool(paused) + `}`37}3839// Public catalogue contains only active orders, never private seller inventory.40// A fresh Snapshot and Buy recheck custody before any wallet signs or settles.41func Listings() string {42	rows := []string{}43	for n := 1; n <= 3333; n++ {44		id := strconv.Itoa(n)45		o := orders[id]46		if o != nil && o.active {47			rows = append(rows, `{"tokenId":`+id+`,"nonce":`+strconv.FormatInt(o.nonce, 10)+`,"priceUgnot":`+strconv.FormatInt(o.price, 10)+`}`)48		}49	}50	return "[" + strings.Join(rows, ",") + "]"51}52func Snapshot(id string) string {53	n, err := strconv.Atoi(id)54	if err != nil || n < 1 || n > 3333 || strconv.Itoa(n) != id {55		panic("store: invalid token ID")56	}57	o := orders[id]58	base := `{"tokenId":` + id + `,"owner":"` + guardians.OwnerOf(id).String() + `","paused":` + strconv.FormatBool(paused)59	if o == nil {60		return base + `,"registered":false,"active":false,"nonce":0,"priceUgnot":0}`61	}62	return base + `,"registered":true,"active":` + strconv.FormatBool(o.active) + `,"nonce":` + strconv.FormatInt(o.nonce, 10) + `,"priceUgnot":` + strconv.FormatInt(o.price, 10) + `}`63}64func HasOrder(id string) bool    { return orders[id] != nil }65func OrderNonce(id string) int64 { return mustOrder(id).nonce }66func OrderPrice(id string) int64 { return mustOrder(id).price }67func IsListed(id string) bool {68	o := orders[id]69	return o != nil && o.active && guardians.OwnerOf(id) == storeAddress70}7172// Register BEFORE the seller directly transfers a selected NFT to this realm.73// The store cannot pull NFTs out of the seller's wallet.74func Register(cur realm, id string) {75	onlySeller(cur)76	noPayment()77	n, err := strconv.Atoi(id)78	if err != nil || n < 1 || n > 3333 || strconv.Itoa(n) != id {79		panic("store: invalid token ID")80	}81	if HasOrder(id) {82		panic("store: already registered")83	}84	if guardians.OwnerOf(id) != Seller {85		panic("store: seller does not own token")86	}87	orders[id] = &order{nonce: freshNonce()}88	chain.Emit("StoreRegistered", "tokenId", id)89}9091// Explicit positive price only. No default price and no free checkout.92func List(cur realm, id string, price, expectedNonce int64) {93	onlySeller(cur)94	noPayment()95	o := currentOrder(id, expectedNonce)96	if guardians.OwnerOf(id) != storeAddress {97		panic("store: token is not deposited")98	}99	if price < 1 || price > maxPrice {100		panic("store: invalid price")101	}102	verifyRoyalty(id, price)103	o.price = price104	o.active = true105	o.nonce = freshNonce()106	chain.Emit("StoreListed", "tokenId", id, "price", strconv.FormatInt(price, 10), "nonce", strconv.FormatInt(o.nonce, 10))107}108109func Unlist(cur realm, id string, expectedNonce int64) {110	onlySeller(cur)111	noPayment()112	o := currentOrder(id, expectedNonce)113	o.active = false114	o.nonce = freshNonce()115	chain.Emit("StoreUnlisted", "tokenId", id)116}117118// Returns selected, unsold inventory even while globally paused. An undeployed119// or unapproved realm must NEVER receive real NFTs.120func Withdraw(cur realm, id string, expectedNonce int64) {121	onlySeller(cur)122	noPayment()123	currentOrder(id, expectedNonce)124	owner := guardians.OwnerOf(id)125	if owner != storeAddress && owner != Seller {126		panic("store: inventory owner changed")127	}128	delete(orders, id)129	if owner == storeAddress {130		guardians.TransferFrom(cross(cur), storeAddress, Seller, id)131	}132	chain.Emit("StoreWithdrawn", "tokenId", id)133}134135func SetPaused(cur realm, value bool) {136	onlySeller(cur)137	noPayment()138	paused = value139	chain.Emit("StorePaused", "paused", strconv.FormatBool(value))140}141142// One MsgCall settles the NFT and both payouts. Any abort rolls back the tx.143// Expected nonce AND price stop a stale checkout accepting edited terms.144func Buy(cur realm, id string, expectedNonce, expectedPrice int64) {145	directUser(cur)146	if paused {147		panic("store: paused")148	}149	buyer := cur.Previous().Address()150	if buyer == Seller {151		panic("store: seller cannot buy")152	}153	o := currentOrder(id, expectedNonce)154	if !o.active || o.price < 1 {155		panic("store: not listed")156	}157	if o.price != expectedPrice {158		panic("store: price changed")159	}160	if guardians.OwnerOf(id) != storeAddress {161		panic("store: inventory owner changed")162	}163	sent := unsafe.OriginSend()164	if len(sent) != 1 || sent[0].Denom != "ugnot" || sent[0].Amount != o.price {165		panic("store: exact payment required")166	}167	fee := verifyRoyalty(id, o.price)168	price := o.price169	delete(orders, id)170	guardians.TransferFrom(cross(cur), storeAddress, buyer, id)171	b := banker.NewBanker(banker.BankerTypeRealmSend, cur)172	b.SendCoins(storeAddress, Seller, chain.NewCoins(chain.NewCoin("ugnot", price-fee)))173	if fee > 0 {174		b.SendCoins(storeAddress, RoyaltyReceiver, chain.NewCoins(chain.NewCoin("ugnot", fee)))175	}176	chain.Emit("StorePurchased", "tokenId", id, "buyer", buyer.String(), "price", strconv.FormatInt(price, 10), "royalty", strconv.FormatInt(fee, 10), "nonce", strconv.FormatInt(expectedNonce, 10))177}178179func verifyRoyalty(id string, price int64) int64 {180	receiver, bps := guardians.DefaultRoyalty()181	actualReceiver, fee := guardians.RoyaltyInfo(id, price)182	if receiver != RoyaltyReceiver || bps != RoyaltyBps || actualReceiver != RoyaltyReceiver || fee != price*RoyaltyBps/10000 {183		panic("store: royalty policy changed")184	}185	return fee186}187func mustOrder(id string) *order {188	o := orders[id]189	if o == nil {190		panic("store: order not found")191	}192	return o193}194func currentOrder(id string, nonce int64) *order {195	o := mustOrder(id)196	if o.nonce != nonce {197		panic("store: stale order")198	}199	return o200}201func freshNonce() int64 {202	if nextNonce >= 9223372036854775806 {203		panic("store: nonce exhausted")204	}205	nextNonce++206	return nextNonce207}208func directUser(cur realm) {209	if !cur.Previous().IsUserCall() {210		panic("store: direct user required")211	}212}213func onlySeller(cur realm) {214	directUser(cur)215	if cur.Previous().Address() != Seller {216		panic("store: seller only")217	}218}219func noPayment() {220	if len(unsafe.OriginSend()) != 0 {221		panic("store: no payment expected")222	}223}224

Functions

  • Address() string

  • Buy(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}, id string, expectedNonce int64, expectedPrice int64)

  • HasOrder(id string) bool

  • Identity() string

  • IsListed(id string) bool

  • List(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}, id string, price int64, expectedNonce int64)

  • Listings() string

  • NextNonce() int64

  • OrderNonce(id string) int64

  • OrderPrice(id string) int64

  • Paused() bool

  • 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}, id string)

  • SetPaused(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}, value bool)

  • Snapshot(id string) string

  • Unlist(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}, id string, expectedNonce int64)

  • Version() 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}, id string, expectedNonce int64)

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

Rendered

RenderedRawgnoweb ↗

Render unavailable

rate limit exceeded — the render query is served by the Gnoland archive RPC.

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.