Search Apps Documentation Source Content File Folder Download Copy

grc721_metadata.gno

2.47 Kb ยท 95 lines
 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}