reads.gno
2.37 Kb · 81 lines
1package memba_points_v1
2
3import (
4 "strings"
5
6 "gno.land/p/nt/ufmt/v0"
7)
8
9// ── Read getters (pure, non-failing; served via vm/qeval) ────────────────────────
10
11// TotalPoints returns the sum of all current points across every account (O(1)).
12func TotalPoints() int64 { return totalPoints }
13
14// HolderCount returns the number of accounts with a positive balance (O(1)).
15func HolderCount() int { return holderCount }
16
17// GetOwner returns the current owner (multisig, or a DAO executor after handoff).
18func GetOwner() address { return owner }
19
20// IsPaused reports whether Award/Revoke are frozen.
21func IsPaused() bool { return paused }
22
23// BalanceJSON returns one account's balance (incl. its on-chain tier) as JSON, or the zero record if
24// the address is unknown. Tier is canonical here — read from the on-chain band ladder — so consumers
25// must NOT re-derive it client-side (see ProfileJSON for points+tier+rank in one call).
26func BalanceJSON(addr string) string {
27 pts, upd := int64(0), int64(0)
28 if v, ok := accounts.Get(addr); ok {
29 a := v.(*Account)
30 pts, upd = a.Points, a.UpdatedAt
31 }
32 return ufmt.Sprintf(`{"addr":"%s","points":%d,"tier":"%s","updatedAt":%d}`,
33 jsonEscape(addr), pts, jsonEscape(tierFor(pts)), upd)
34}
35
36// GetAwardersJSON returns the whitelisted awarder realm pkgpaths as a JSON string array (bounded —
37// the whitelist is small + owner-managed). Public "who may mint points" transparency.
38func GetAwardersJSON() string {
39 var sb strings.Builder
40 sb.WriteString("[")
41 first := true
42 awarders.Iterate("", "", func(k string, _ any) bool {
43 if !first {
44 sb.WriteString(",")
45 }
46 first = false
47 sb.WriteString(`"`)
48 sb.WriteString(jsonEscape(k))
49 sb.WriteString(`"`)
50 return false
51 })
52 sb.WriteString("]")
53 return sb.String()
54}
55
56// jsonEscape escapes a string for embedding in a JSON string literal. Addresses are bech32 and
57// awarder keys are pkgpaths, but the read path escapes defensively regardless.
58func jsonEscape(s string) string {
59 var sb strings.Builder
60 for _, r := range s {
61 switch r {
62 case '"':
63 sb.WriteString("\\\"")
64 case '\\':
65 sb.WriteString("\\\\")
66 case '\n':
67 sb.WriteString("\\n")
68 case '\r':
69 sb.WriteString("\\r")
70 case '\t':
71 sb.WriteString("\\t")
72 default:
73 if r < 0x20 {
74 sb.WriteString(ufmt.Sprintf("\\u%04x", r))
75 } else {
76 sb.WriteString(string(r))
77 }
78 }
79 }
80 return sb.String()
81}