grc721_metadata.gno
3.43 Kb · 130 lines
1package grc721
2
3import (
4 "chain"
5
6 "gno.land/p/nt/avl/v0"
7)
8
9// metadataNFT represents an NFT with metadata extensions.
10type metadataNFT struct {
11 *BasicNFT
12 extensions *avl.Tree // AVL tree for storing metadata extensions
13}
14
15// Ensure that metadataNFT implements the IGRC721MetadataOnchain interface.
16var _ IGRC721MetadataOnchain = (*metadataNFT)(nil)
17
18// NewNFTWithMetadata creates a new basic NFT with metadata extensions.
19func NewNFTWithMetadata(_ int, rlm realm, name, symbol string) *metadataNFT {
20 return &metadataNFT{
21 BasicNFT: NewBasicNFT(0, rlm, name, symbol),
22 extensions: avl.NewTree(),
23 }
24}
25
26// SetTokenMetadata sets metadata for a given token ID. The token must exist and
27// caller must equal its owner; the owning realm's wrapper derives caller from
28// rlm.Previous().Address() under IsCurrent (mirrors SetTokenRoyalty).
29func (s *metadataNFT) SetTokenMetadata(caller address, tid TokenID, metadata Metadata) error {
30 // Check that the token exists and the caller is its owner.
31 owner, err := s.OwnerOf(tid)
32 if err != nil {
33 return err
34 }
35 if caller != owner {
36 return ErrCallerIsNotOwner
37 }
38
39 // Set the metadata for the token ID in the extensions AVL tree
40 s.extensions.Set(tid.String(), metadata)
41
42 chain.Emit(
43 MetadataUpdateEvent,
44 "token", s.ID(),
45 "tokenId", tid.String(),
46 )
47
48 return nil
49}
50
51// TokenMetadata retrieves metadata for a given token ID.
52func (s *metadataNFT) TokenMetadata(tid TokenID) (Metadata, error) {
53 // Retrieve metadata from the extensions AVL tree
54 metadata, found := s.extensions.Get(tid.String())
55 if !found {
56 return Metadata{}, ErrInvalidTokenId
57 }
58
59 return metadata.(Metadata), nil
60}
61
62// Basic NFT methods forwarded to embedded BasicNFT
63
64func (s *metadataNFT) Name() string {
65 return s.BasicNFT.Name()
66}
67
68func (s *metadataNFT) Symbol() string {
69 return s.BasicNFT.Symbol()
70}
71
72func (s *metadataNFT) TokenCount() int64 {
73 return s.BasicNFT.TokenCount()
74}
75
76func (s *metadataNFT) BalanceOf(addr address) (int64, error) {
77 return s.BasicNFT.BalanceOf(addr)
78}
79
80func (s *metadataNFT) OwnerOf(tid TokenID) (address, error) {
81 return s.BasicNFT.OwnerOf(tid)
82}
83
84func (s *metadataNFT) TokenURI(tid TokenID) (string, error) {
85 return s.BasicNFT.TokenURI(tid)
86}
87
88func (s *metadataNFT) SetTokenURI(caller address, tid TokenID, tURI TokenURI) (bool, error) {
89 return s.BasicNFT.SetTokenURI(caller, tid, tURI)
90}
91
92func (s *metadataNFT) IsApprovedForAll(owner, operator address) bool {
93 return s.BasicNFT.IsApprovedForAll(owner, operator)
94}
95
96func (s *metadataNFT) Approve(caller, to address, tid TokenID) error {
97 return s.BasicNFT.Approve(caller, to, tid)
98}
99
100func (s *metadataNFT) GetApproved(tid TokenID) (address, error) {
101 return s.BasicNFT.GetApproved(tid)
102}
103
104func (s *metadataNFT) SetApprovalForAll(caller, operator address, approved bool) error {
105 return s.BasicNFT.SetApprovalForAll(caller, operator, approved)
106}
107
108func (s *metadataNFT) SafeTransferFrom(caller, from, to address, tid TokenID) error {
109 return s.BasicNFT.SafeTransferFrom(caller, from, to, tid)
110}
111
112func (s *metadataNFT) TransferFrom(caller, from, to address, tid TokenID) error {
113 return s.BasicNFT.TransferFrom(caller, from, to, tid)
114}
115
116func (s *metadataNFT) Mint(to address, tid TokenID) error {
117 return s.BasicNFT.Mint(to, tid)
118}
119
120func (s *metadataNFT) SafeMint(to address, tid TokenID) error {
121 return s.BasicNFT.SafeMint(to, tid)
122}
123
124func (s *metadataNFT) Burn(tid TokenID) error {
125 return s.BasicNFT.Burn(tid)
126}
127
128func (s *metadataNFT) RenderHome() string {
129 return s.BasicNFT.RenderHome()
130}