transfer.gno
3.54 Kb · 116 lines
1package memba_collections
2
3import (
4 "chain"
5
6 "gno.land/p/samcrew/grc721"
7)
8
9// ── Owner approvals ─────────────────────────────────────────────────────────
10
11// Approve grants single-token transfer approval. Caller must own/operate.
12func Approve(cur realm, id string, operator address, tid grc721.TokenID) {
13 c := mustGet(id)
14 if err := c.nft.Approve(caller(), operator, tid); err != nil {
15 panic(err.Error())
16 }
17}
18
19// SetApprovalForAll grants/revokes operator approval for all the caller's
20// tokens in the collection (this is how a seller authorizes a marketplace).
21func SetApprovalForAll(cur realm, id string, operator address, approved bool) {
22 c := mustGet(id)
23 if err := c.nft.SetApprovalForAll(caller(), operator, approved); err != nil {
24 panic(err.Error())
25 }
26}
27
28// ── Burn ─────────────────────────────────────────────────────────────────────
29
30// Burn destroys a token the caller owns and clears any per-token royalty.
31// Burning never reopens a supply slot (nextAutoTokenID only increments, S-2).
32func Burn(cur realm, id string, tid grc721.TokenID) {
33 c := mustGet(id)
34 owner, err := c.nft.OwnerOf(tid)
35 if err != nil {
36 panic(err.Error())
37 }
38 if caller() != owner {
39 panic("caller is not owner")
40 }
41 if err := c.nft.Burn(tid); err != nil {
42 panic(err.Error())
43 }
44 c.tokenRoyalty.Remove(string(tid))
45 chain.Emit("Burned", "collectionID", id, "tokenId", string(tid), "owner", owner.String())
46}
47
48// ── Settlement (registered markets only) ─────────────────────────────────────
49
50func isRegisteredMarket(a address) bool {
51 v, ok := registeredMarkets.Get(a.String())
52 return ok && v.(bool)
53}
54
55// MarketTransfer is the ONLY token-movement path. Only a registered market
56// realm may call it; it moves the token via the realm's internal ledger with
57// the market as the grc721 caller (the seller must have approved the market).
58func MarketTransfer(cur realm, id string, from, to address, tid grc721.TokenID) {
59 market := caller()
60 if !isRegisteredMarket(market) {
61 panic("unauthorized market")
62 }
63 c := mustGet(id)
64 assertNotPaused(c)
65 if err := c.nft.TransferFrom(market, from, to, tid); err != nil {
66 panic(err.Error())
67 }
68 chain.Emit("MarketTransfer",
69 "collectionID", id,
70 "from", from.String(),
71 "to", to.String(),
72 "tokenId", string(tid),
73 )
74}
75
76// ── Reads (IGRC721Reader surface + URI) ──────────────────────────────────────
77
78func OwnerOf(id string, tid grc721.TokenID) address {
79 o, err := mustGet(id).nft.OwnerOf(tid)
80 if err != nil {
81 panic(err.Error())
82 }
83 return o
84}
85
86func BalanceOf(id string, owner address) int64 {
87 b, err := mustGet(id).nft.BalanceOf(owner)
88 if err != nil {
89 panic(err.Error())
90 }
91 return b
92}
93
94func GetApproved(id string, tid grc721.TokenID) address {
95 a, err := mustGet(id).nft.GetApproved(tid)
96 if err != nil {
97 return ""
98 }
99 return a
100}
101
102func IsApprovedForAll(id string, owner, operator address) bool {
103 return mustGet(id).nft.IsApprovedForAll(owner, operator)
104}
105
106func TokenURI(id string, tid grc721.TokenID) string {
107 u, err := mustGet(id).nft.TokenURI(tid)
108 if err != nil {
109 return ""
110 }
111 return u
112}
113
114func TokenCount(id string) int64 { return mustGet(id).nft.TokenCount() }
115
116func IsRegisteredMarket(a address) bool { return isRegisteredMarket(a) }