1package grc721
2
3import (
4 "std"
5
6 "gno.land/p/demo/avl"
7)
8
9// metadataNFT represents an NFT with metadata extensions.
10type metadataNFT struct {
11 *basicNFT // Embedded basicNFT struct for basic NFT functionality
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(name string, symbol string) *metadataNFT {
20 // Create a new basic NFT
21 nft := NewBasicNFT(name, symbol)
22
23 // Return a metadataNFT with basicNFT embedded and an empty AVL tree for extensions
24 return &metadataNFT{
25 basicNFT: nft,
26 extensions: avl.NewTree(),
27 }
28}
29
30// SetTokenMetadata sets metadata for a given token ID.
31func (s *metadataNFT) SetTokenMetadata(tid TokenID, metadata Metadata) error {
32 // Check if the caller is the owner of the token
33 owner, err := s.basicNFT.OwnerOf(tid)
34 if err != nil {
35 return err
36 }
37 caller := std.PrevRealm().Addr()
38 if caller != owner {
39 return ErrCallerIsNotOwner
40 }
41
42 // Set the metadata for the token ID in the extensions AVL tree
43 s.extensions.Set(string(tid), metadata)
44 return nil
45}
46
47// TokenMetadata retrieves metadata for a given token ID.
48func (s *metadataNFT) TokenMetadata(tid TokenID) (Metadata, error) {
49 // Retrieve metadata from the extensions AVL tree
50 metadata, found := s.extensions.Get(string(tid))
51 if !found {
52 return Metadata{}, ErrInvalidTokenId
53 }
54
55 return metadata.(Metadata), nil
56}
57
58// mint mints a new token and assigns it to the specified address.
59func (s *metadataNFT) mint(to std.Address, tid TokenID) error {
60 // Check if the address is valid
61 if err := isValidAddress(to); err != nil {
62 return err
63 }
64
65 // Check if the token ID already exists
66 if s.basicNFT.exists(tid) {
67 return ErrTokenIdAlreadyExists
68 }
69
70 s.basicNFT.beforeTokenTransfer(zeroAddress, to, tid, 1)
71
72 // Check if the token ID was minted by beforeTokenTransfer
73 if s.basicNFT.exists(tid) {
74 return ErrTokenIdAlreadyExists
75 }
76
77 // Increment balance of the recipient address
78 toBalance, err := s.basicNFT.BalanceOf(to)
79 if err != nil {
80 return err
81 }
82 toBalance += 1
83 s.basicNFT.balances.Set(to.String(), toBalance)
84
85 // Set owner of the token ID to the recipient address
86 s.basicNFT.owners.Set(string(tid), to)
87
88 // Emit transfer event
89 event := TransferEvent{zeroAddress, to, tid}
90 emit(&event)
91
92 s.basicNFT.afterTokenTransfer(zeroAddress, to, tid, 1)
93
94 return nil
95}
grc721_metadata.gno
2.47 Kb ยท 95 lines