Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

reads.gno

5.76 Kb · 198 lines
  1package core
  2
  3import (
  4	"chain"
  5	"strings"
  6
  7	"gno.land/p/nt/ufmt/v0"
  8
  9	"gno.land/p/g1pq6pxhgxk2uw5shg5le6glfydpxcu74k0zh069/sinopia/safe/v1"
 10	"gno.land/p/g1pq6pxhgxk2uw5shg5le6glfydpxcu74k0zh069/sinopia/types/v1"
 11)
 12
 13// Every function in this file is read-only (I-12: no exported non-crossing
 14// mutator). Lists are paginated with limit <= MaxPageSize (RA L-4).
 15
 16// SelfAddress is core's package address, for the deploy-time cross-check
 17// against scripts/pkgaddr.py (RA H-5).
 18func SelfAddress() address { return chain.PackageAddress(selfPath) }
 19
 20func CollectionCount() int64 { return collCount }
 21
 22// MintedTotal counts every token ever minted, burned ones included (OA B4).
 23func MintedTotal(cid string) int64 { return mustCollection(cid).minted() }
 24
 25// MintedBy is the lifetime mint counter of addr in cid (OA B3, I-9).
 26func MintedBy(cid string, addr address) int64 { return mintedBy(mustCollection(cid), addr) }
 27
 28// Info is the typed collection view for other realms.
 29func Info(cid string) types.CollectionInfo {
 30	c := mustCollection(cid)
 31	info := types.CollectionInfo{
 32		ID:          c.id,
 33		Name:        c.name,
 34		Symbol:      c.symbol,
 35		Description: c.description,
 36		Creator:     c.creator,
 37		Minter:      c.minter,
 38		EngineID:    c.engineID,
 39		Params:      c.params,
 40		State:       stateAt(c, height()),
 41		MaxSupply:   c.maxSupply,
 42		Minted:      c.minted(),
 43		Reserved:    c.reserved,
 44		StartHeight: c.startHeight,
 45		EndHeight:   c.endHeight,
 46		RoyaltyBps:  c.royaltyBps,
 47	}
 48	if c.prov != nil {
 49		info.RevealDeadline = revealDeadline(c)
 50		info.Badge = c.prov.badge
 51	}
 52	return info
 53}
 54
 55// PrimaryPayees returns a copy of the frozen primary-sale split.
 56func PrimaryPayees(cid string) []types.Payee {
 57	return append([]types.Payee{}, mustCollection(cid).primaryPayees...)
 58}
 59
 60// FeeConfig is the typed fee view minters and markets settle with.
 61func FeeConfig() types.Fees { return fees }
 62
 63// PrimaryFeeBps is the protocol fee on cid's primary sale: the fee at
 64// Launch, or the current one if the admin lowered it since (SA-I5: a fee
 65// cannot rise during a sale).
 66func PrimaryFeeBps(cid string) int64 {
 67	c := mustCollection(cid)
 68	if c.prov != nil && c.primaryBps < fees.PrimaryBps {
 69		return c.primaryBps
 70	}
 71	return fees.PrimaryBps
 72}
 73
 74func Beacon() address { return beacon }
 75
 76func Admin() address { return admin }
 77
 78func IsMinter(path string) bool {
 79	v := minters.Get(path)
 80	return v != nil && !v.(*minterRecord).deprecated
 81}
 82
 83// Collection is the collection record as JSON.
 84func Collection(cid string) string {
 85	w := &safe.JSONWriter{}
 86	writeCollection(w, mustCollection(cid))
 87	return w.String()
 88}
 89
 90func Collections(offset, limit int64) string {
 91	w := &safe.JSONWriter{}
 92	w.BeginArray()
 93	collections.IterateByOffset(int(offset), int(clampLimit(limit)), func(_ string, v any) bool {
 94		writeCollection(w, v.(*collection))
 95		return false
 96	})
 97	w.EndArray()
 98	return w.String()
 99}
100
101func CollectionsByCreator(creator address, offset, limit int64) string {
102	w := &safe.JSONWriter{}
103	w.BeginArray()
104	prefix := creator.String() + ":"
105	skipped, written, want := int64(0), int64(0), clampLimit(limit)
106	byCreator.Iterate(prefix, prefix+"\xff", func(_ string, v any) bool {
107		if skipped < offset {
108			skipped++
109			return false
110		}
111		writeCollection(w, mustCollection(v.(string)))
112		written++
113		return written >= want
114	})
115	w.EndArray()
116	return w.String()
117}
118
119// Fees is the fee configuration and its hard caps as JSON.
120func Fees() string {
121	w := &safe.JSONWriter{}
122	w.BeginObject()
123	w.IntField("createFee", fees.CreateFee)
124	w.IntField("primaryBps", fees.PrimaryBps)
125	w.IntField("secondaryBps", fees.SecondaryBps)
126	w.StrField("treasury", fees.Treasury.String())
127	w.IntField("createFeeCap", CreateFeeCap)
128	w.IntField("protocolFeeCapBps", ProtocolFeeCapBps)
129	w.IntField("royaltyCapBps", RoyaltyCapBps)
130	w.EndObject()
131	return w.String()
132}
133
134// PendingOps is the timelock queue as JSON.
135func PendingOps() string {
136	w := &safe.JSONWriter{}
137	w.BeginArray()
138	ops.Iterate("", "", func(_ string, v any) bool {
139		p := v.(*pendingOp)
140		w.BeginObject()
141		w.StrField("id", itoa(p.id))
142		w.StrField("op", p.op)
143		w.StrField("arg", p.arg)
144		w.IntField("proposed", p.proposed)
145		w.IntField("earliest", earliestExecution(p))
146		w.EndObject()
147		return false
148	})
149	w.EndArray()
150	return w.String()
151}
152
153func writeCollection(w *safe.JSONWriter, c *collection) {
154	h := height()
155	w.BeginObject()
156	w.StrField("cid", c.id)
157	w.StrField("name", c.name)
158	w.StrField("symbol", c.symbol)
159	w.StrField("description", c.description)
160	w.StrField("creator", c.creator.String())
161	w.StrField("engine", c.engineID)
162	w.StrField("params", c.params)
163	w.StrField("minter", c.minter)
164	w.StrField("state", stateAt(c, h).String())
165	w.IntField("maxSupply", c.maxSupply)
166	w.IntField("minted", c.minted())
167	w.IntField("reserved", c.reserved)
168	w.IntField("royaltyBps", c.royaltyBps)
169	w.StrField("royaltyAddress", royaltyAddress(c.id).String())
170	w.StrField("primaryPayees", safe.FormatPayees(c.primaryPayees))
171	w.StrField("royaltyPayees", safe.FormatPayees(c.royaltyPayees))
172	w.IntField("startHeight", c.startHeight)
173	w.IntField("endHeight", c.endHeight)
174	w.IntField("createdHeight", c.createdHeight)
175	w.StrField("token", c.token.ID())
176	if c.prov != nil {
177		w.IntField("revealDeadline", revealDeadline(c))
178		w.BoolField("useBeacon", c.useBeacon)
179		w.StrField("badge", c.prov.badge)
180		w.BoolField("fair", FairLaunch(c.id))
181	}
182	w.EndObject()
183}
184
185func clampLimit(limit int64) int64 {
186	if limit <= 0 || limit > MaxPageSize {
187		return MaxPageSize
188	}
189	return limit
190}
191
192// Render stays minimal in the immutable realm; the browsable gallery is the
193// private, re-deployable gallery realm (design §2.5.7).
194func Render(path string) string {
195	gallery := strings.TrimPrefix(strings.TrimSuffix(selfPath, "/core")+"/gallery", "gno.land")
196	return ufmt.Sprintf("# Collections ledger\n\n%d collections, %d engines. Browse them in the [gallery](%s).\n",
197		collCount, engineCount, gallery)
198}