minter.gno
3.34 Kb · 114 lines
1// GnoMoji — Minter Realm
2// gno.land/r/g138gdmwj6heduu3st796lw6qqdwylgaxf7ty5gz/minter4
3//
4// Treasury gateway for GnoMoji on Gno.land (v1.5.0 / Onyx testnet API).
5// Called server-side by treasury.server.ts after a player earns coins via ClaimMine.
6//
7// Security: only the admin (treasury wallet, set at deploy time) can call Mint or MintTool.
8
9package minter4
10
11import (
12 "strconv"
13 "strings"
14
15 "gno.land/p/nt/avl/v0"
16 "gno.land/p/nt/ufmt/v0"
17 coinsRealm "gno.land/r/g138gdmwj6heduu3st796lw6qqdwylgaxf7ty5gz/coins"
18 gameRealm "gno.land/r/g138gdmwj6heduu3st796lw6qqdwylgaxf7ty5gz/game3"
19)
20
21var (
22 admin address
23 mintLogs avl.Tree // addr+":"+coinId → total minted (audit)
24)
25
26func init(cur realm) {
27 admin = cur.Previous().Address()
28}
29
30func isAdmin(cur realm) bool {
31 return cur.Previous().Address() == admin
32}
33
34// UpdateAdmin transfers the admin role to a new address.
35func UpdateAdmin(cur realm, newAdmin string) {
36 if !isAdmin(cur) {
37 panic("minter: unauthorized")
38 }
39 admin = address(newAdmin)
40}
41
42// AdminAddr returns the current admin address.
43func AdminAddr() string {
44 return admin.String()
45}
46
47// Mint credits coinId tokens to a player address.
48// Records in internal audit log and issues real tokens via the coins realm.
49func Mint(cur realm, coinId string, toAddr string, amountStr string) {
50 if !isAdmin(cur) {
51 panic("minter: unauthorized — only treasury can mint")
52 }
53 if coinId == "" || toAddr == "" {
54 panic("minter: coinId and toAddr required")
55 }
56 if !strings.HasPrefix(toAddr, "g1") {
57 panic("minter: invalid Gno.land address")
58 }
59 amount, err := strconv.ParseUint(amountStr, 10, 64)
60 if err != nil || amount == 0 {
61 panic("minter: invalid amount")
62 }
63
64 // Update audit log
65 key := toAddr + ":" + coinId
66 existing := uint64(0)
67 if mintLogs.Has(key) {
68 existing, _ = strconv.ParseUint(mintLogs.Get(key).(string), 10, 64)
69 }
70 mintLogs.Set(key, strconv.FormatUint(existing+amount, 10))
71
72 // Issue real tokens via the coins realm (cross-realm call)
73 coinsRealm.Mint(cross(cur), coinId, toAddr, amountStr)
74}
75
76// MintTool records tool ownership for a player on-chain.
77func MintTool(cur realm, toolId string, toAddr string, _ string) {
78 if !isAdmin(cur) {
79 panic("minter: unauthorized — only treasury can mint tools")
80 }
81 if toolId == "" || toAddr == "" {
82 panic("minter: toolId and toAddr required")
83 }
84 mintLogs.Set(toAddr+":tool:"+toolId, "1")
85}
86
87// ClearPendingMints notifies the game realm that coins have been minted.
88// Forwards the call to game3.ClearPendingMints to clear the player's pending balance.
89func ClearPendingMints(cur realm, playerAddr string, coinsJson string) {
90 if !isAdmin(cur) {
91 panic("minter: unauthorized")
92 }
93 if playerAddr == "" {
94 return
95 }
96 gameRealm.ClearPendingMints(cross(cur), playerAddr, coinsJson)
97}
98
99// ── Queries ───────────────────────────────────────────────────────────────────
100
101func TotalMinted(playerAddr string, coinId string) string {
102 key := playerAddr + ":" + coinId
103 if mintLogs.Has(key) {
104 return mintLogs.Get(key).(string)
105 }
106 return "0"
107}
108
109func Render(_ string) string {
110 return ufmt.Sprintf(
111 "# GnoMoji Minter\n\nAdmin: `%s`\n\nPath: `gno.land/r/g138gdmwj6heduu3st796lw6qqdwylgaxf7ty5gz/minter4`\n\nUse Mint(coinId, addr, amount) to credit coins after ClaimMine.\n",
112 admin.String(),
113 )
114}