Search Apps Documentation Source Content File Folder Download Copy Actions Download

registry.gno

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