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}224Address() 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.
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.