Search Apps Documentation Source Content File Folder Download Copy Actions Download

registry.gno

4.13 Kb ยท 196 lines
  1package nftregistry6
  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	callerRealm := runtime.PreviousRealm().Address()
 52	if callerRealm != realmAddr {
 53		panic("Security: realm address mismatch")
 54	}
 55
 56	// Check if collection already registered
 57	if collections.Has(realmAddr.String()) {
 58		panic("Collection already registered")
 59	}
 60
 61	if getter == nil {
 62		panic("NFT getter function is required")
 63	}
 64
 65	if name == "" || symbol == "" {
 66		panic("Name and symbol cannot be empty")
 67	}
 68
 69	info := &CollectionInfo{
 70		Address:          realmAddr,
 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(realmAddr.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}