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}