registry.gno
4.01 Kb ยท 191 lines
1package nftregistry8
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 realmAddr address,
41 name string,
42 symbol string,
43 category string,
44 description string,
45 externalURL string,
46 supportsMetadata bool,
47 getter grc721.NFTGetter,
48) {
49 creator := runtime.OriginCaller()
50
51 // Check if collection already registered
52 if collections.Has(realmAddr.String()) {
53 panic("Collection already registered")
54 }
55
56 if getter == nil {
57 panic("NFT getter function is required")
58 }
59
60 if name == "" || symbol == "" {
61 panic("Name and symbol cannot be empty")
62 }
63
64 info := &CollectionInfo{
65 Address: realmAddr,
66 Creator: creator,
67 Name: name,
68 Symbol: symbol,
69 RegisteredAt: runtime.ChainHeight(),
70 Verified: false,
71 Category: category,
72 Description: description,
73 ExternalURL: externalURL,
74 NFTGetter: getter,
75 SupportsMetadata: supportsMetadata,
76 }
77
78 collections.Set(realmAddr.String(), info)
79}
80
81func IsRegistered(collectionAddr address) bool {
82 return collections.Has(collectionAddr.String())
83}
84
85func GetTotalCollections() int {
86 count := 0
87 collections.Iterate("", "", func(key string, value interface{}) bool {
88 count++
89 return false
90 })
91 return count
92}
93
94func GetVerifiedCount() int {
95 count := 0
96 collections.Iterate("", "", func(key string, value interface{}) bool {
97 info := value.(*CollectionInfo)
98 if info.Verified {
99 count++
100 }
101 return false
102 })
103 return count
104}
105
106func GetCollection(collectionAddr address) *CollectionInfo {
107 val, exists := collections.Get(collectionAddr.String())
108 if !exists {
109 return nil
110 }
111 return val.(*CollectionInfo)
112}
113
114func GetNFTGetter(collectionAddr address) (grc721.NFTGetter, bool) {
115 info := GetCollection(collectionAddr)
116 if info == nil {
117 return nil, false
118 }
119 return info.NFTGetter, true
120}
121
122func GetTokenMetadata(collectionAddr address, tokenId grc721.TokenID) (grc721.Metadata, error) {
123 info := GetCollection(collectionAddr)
124 if info == nil {
125 panic("Collection not registered")
126 }
127
128 if !info.SupportsMetadata {
129 panic("Collection does not support onchain metadata")
130 }
131
132 nftInstance := info.NFTGetter()
133 metadataCollection := nftInstance.(grc721.IGRC721MetadataOnchain)
134
135 return metadataCollection.TokenMetadata(tokenId)
136}
137
138func VerifyCollection(collectionAddr address) {
139 caller := runtime.PreviousRealm().Address()
140
141 if !isAdmin(caller) {
142 panic("Only admins can verify collections")
143 }
144
145 info := GetCollection(collectionAddr)
146 if info == nil {
147 panic("Collection not found")
148 }
149
150 if !info.Verified {
151 info.Verified = true
152 collections.Set(collectionAddr.String(), info)
153 }
154}
155
156func UnverifyCollection(collectionAddr address) {
157 caller := runtime.PreviousRealm().Address()
158
159 if !isAdmin(caller) {
160 panic("Only admins can unverify collections")
161 }
162
163 info := GetCollection(collectionAddr)
164 if info == nil {
165 panic("Collection not found")
166 }
167
168 if info.Verified {
169 info.Verified = false
170 collections.Set(collectionAddr.String(), info)
171 }
172}
173
174func UpdateCollectionInfo(category, description, externalURL string) {
175 caller := runtime.PreviousRealm().Address()
176
177 info := GetCollection(caller)
178 if info == nil {
179 panic("Collection not registered")
180 }
181
182 info.Category = category
183 info.Description = description
184 info.ExternalURL = externalURL
185 collections.Set(caller.String(), info)
186}
187
188func isAdmin(addr address) bool {
189 _, exists := admins.Get(addr.String())
190 return exists
191}