registry.gno
4.03 Kb ยท 192 lines
1package nftregistry4
2
3import (
4 "chain/runtime"
5
6 "gno.land/p/nt/avl"
7 "gno.land/p/demo/tokens/grc721"
8)
9
10// CollectionInfo - Extended metadata stored in the registry
11type CollectionInfo struct {
12 Address address
13 Name string
14 Symbol string
15 Creator address
16 RegisteredAt int64
17 Verified bool
18 Category string
19 Description string
20 ExternalURL string
21 NFTGetter grc721.NFTGetter
22 SupportsMetadata bool
23}
24
25var (
26 collections avl.Tree
27 admins avl.Tree
28 categoriesIndex avl.Tree
29 owner address
30 registrationFee int64 = 1000000
31)
32
33func init() {
34 owner = runtime.PreviousRealm().Address()
35 admins.Set(owner.String(), true)
36}
37
38// RegisterCollection - Register a new NFT collection
39func RegisterCollection(
40 name string,
41 symbol string,
42 category string,
43 description string,
44 externalURL string,
45 supportsMetadata bool,
46 getter grc721.NFTGetter,
47) {
48 caller := runtime.PreviousRealm().Address()
49
50 // Check if collection already registered
51 if collections.Has(caller.String()) {
52 panic("Collection already registered")
53 }
54
55 if getter == nil {
56 panic("NFT getter function is required")
57 }
58
59 // Validate inputs
60 if name == "" || symbol == "" {
61 panic("Name and symbol cannot be empty")
62 }
63
64 // Create collection info
65 info := &CollectionInfo{
66 Address: caller,
67 Name: name,
68 Symbol: symbol,
69 Creator: caller,
70 RegisteredAt: runtime.ChainHeight(),
71 Verified: false,
72 Category: category,
73 Description: description,
74 ExternalURL: externalURL,
75 NFTGetter: getter,
76 SupportsMetadata: supportsMetadata,
77 }
78
79 collections.Set(caller.String(), info)
80}
81
82func IsRegistered(collectionAddr address) bool {
83 return collections.Has(collectionAddr.String())
84}
85
86func GetTotalCollections() int {
87 count := 0
88 collections.Iterate("", "", func(key string, value interface{}) bool {
89 count++
90 return false
91 })
92 return count
93}
94
95func GetVerifiedCount() int {
96 count := 0
97 collections.Iterate("", "", func(key string, value interface{}) bool {
98 info := value.(*CollectionInfo)
99 if info.Verified {
100 count++
101 }
102 return false
103 })
104 return count
105}
106
107func GetCollection(collectionAddr address) *CollectionInfo {
108 val, exists := collections.Get(collectionAddr.String())
109 if !exists {
110 return nil
111 }
112 return val.(*CollectionInfo)
113}
114
115func GetNFTGetter(collectionAddr address) (grc721.NFTGetter, bool) {
116 info := GetCollection(collectionAddr)
117 if info == nil {
118 return nil, false
119 }
120 return info.NFTGetter, true
121}
122
123func GetTokenMetadata(collectionAddr address, tokenId grc721.TokenID) (grc721.Metadata, error) {
124 info := GetCollection(collectionAddr)
125 if info == nil {
126 panic("Collection not registered")
127 }
128
129 if !info.SupportsMetadata {
130 panic("Collection does not support onchain metadata")
131 }
132
133 nftInstance := info.NFTGetter()
134 metadataCollection := nftInstance.(grc721.IGRC721MetadataOnchain)
135
136 return metadataCollection.TokenMetadata(tokenId)
137}
138
139func VerifyCollection(collectionAddr address) {
140 caller := runtime.PreviousRealm().Address()
141
142 if !isAdmin(caller) {
143 panic("Only admins can verify collections")
144 }
145
146 info := GetCollection(collectionAddr)
147 if info == nil {
148 panic("Collection not found")
149 }
150
151 if !info.Verified {
152 info.Verified = true
153 collections.Set(collectionAddr.String(), info)
154 }
155}
156
157func UnverifyCollection(collectionAddr address) {
158 caller := runtime.PreviousRealm().Address()
159
160 if !isAdmin(caller) {
161 panic("Only admins can unverify collections")
162 }
163
164 info := GetCollection(collectionAddr)
165 if info == nil {
166 panic("Collection not found")
167 }
168
169 if info.Verified {
170 info.Verified = false
171 collections.Set(collectionAddr.String(), info)
172 }
173}
174
175func UpdateCollectionInfo(category, description, externalURL string) {
176 caller := runtime.PreviousRealm().Address()
177
178 info := GetCollection(caller)
179 if info == nil {
180 panic("Collection not registered")
181 }
182
183 info.Category = category
184 info.Description = description
185 info.ExternalURL = externalURL
186 collections.Set(caller.String(), info)
187}
188
189func isAdmin(addr address) bool {
190 _, exists := admins.Get(addr.String())
191 return exists
192}