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