Smart Contract

InceptionAvatar

A.83ed64a1d4f3833f.InceptionAvatar

Valid From

86,741,778

Deployed

1w ago
Feb 16, 2026, 03:58:08 AM UTC

Dependents

3346 imports
1// SPDX-License-Identifier: MIT
2import NonFungibleToken from 0x1d7e57aa55817448
3import ViewResolver from 0x1d7e57aa55817448
4import MetadataViews from 0x1d7e57aa55817448
5
6access(all)
7contract InceptionAvatar: NonFungibleToken{ 
8	access(all)
9	event ContractInitialized()
10	
11	access(all)
12	event SetCreated(setID: UInt64)
13	
14	access(all)
15	event NFTTemplateCreated(templateID: UInt64, metadata:{ String: String})
16	
17	access(all)
18	event Withdraw(id: UInt64, from: Address?)
19	
20	access(all)
21	event Deposit(id: UInt64, to: Address?)
22	
23	access(all)
24	event Minted(id: UInt64, templateID: UInt64)
25	
26	access(all)
27	event TemplateAddedToSet(setID: UInt64, templateID: UInt64)
28	
29	access(all)
30	event TemplateLockedFromSet(setID: UInt64, templateID: UInt64)
31	
32	access(all)
33	event TemplateUpdated(template: InceptionAvatarTemplate)
34	
35	access(all)
36	event SetLocked(setID: UInt64)
37	
38	access(all)
39	let CollectionStoragePath: StoragePath
40	
41	access(all)
42	let CollectionPublicPath: PublicPath
43	
44	access(all)
45	let AdminStoragePath: StoragePath
46	
47	access(all)
48	var totalSupply: UInt64
49	
50	access(all)
51	var nextTemplateID: UInt64
52	
53	access(all)
54	var nextSetID: UInt64
55	
56	access(all)
57	var InceptionAvatarTemplates:{ UInt64: InceptionAvatarTemplate}
58	
59	access(all)
60	var sets: @{UInt64: Set}
61	
62	access(all)
63	resource interface InceptionAvatarCollectionPublic{ 
64		access(all)
65		fun deposit(token: @{NonFungibleToken.NFT}): Void
66		
67		access(all)
68		view fun getIDs(): [UInt64]
69		
70		access(all)
71		view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}?
72		
73		access(all)
74		fun borrowInceptionAvatar(id: UInt64): &InceptionAvatar.NFT?{ 
75			post{ 
76				result == nil || result?.id == id:
77					"Cannot borrow InceptionAvatar reference: The ID of the returned reference is incorrect"
78			}
79		}
80	}
81	
82	access(all)
83	struct InceptionAvatarTemplate{ 
84		access(all)
85		let templateID: UInt64
86		
87		access(all)
88		var name: String
89		
90		access(all)
91		var description: String
92		
93		access(all)
94		var locked: Bool
95		
96		access(all)
97		var addedToSet: UInt64
98		
99		access(self)
100		var metadata:{ String: String}
101		
102		access(all)
103		fun getMetadata():{ String: String}{ 
104			return self.metadata
105		}
106		
107		access(all)
108		fun lockTemplate(){ 
109			self.locked = true
110		}
111		
112		access(all)
113		fun updateMetadata(newMetadata:{ String: String}){ 
114			pre{ 
115				newMetadata.length != 0:
116					"New Template metadata cannot be empty"
117			}
118			self.metadata = newMetadata
119		}
120		
121		access(all)
122		fun markAddedToSet(setID: UInt64){ 
123			self.addedToSet = setID
124		}
125		
126		init(templateID: UInt64, name: String, description: String, metadata:{ String: String}){ 
127			pre{ 
128				metadata.length != 0:
129					"New Template metadata cannot be empty"
130			}
131			self.templateID = templateID
132			self.name = name
133			self.description = description
134			self.metadata = metadata
135			self.locked = false
136			self.addedToSet = 0
137			InceptionAvatar.nextTemplateID = InceptionAvatar.nextTemplateID + 1
138			emit NFTTemplateCreated(templateID: self.templateID, metadata: self.metadata)
139		}
140	}
141	
142	access(all)
143	resource NFT: NonFungibleToken.NFT, ViewResolver.Resolver{ 
144		access(all)
145		let id: UInt64
146		
147		access(all)
148		let templateID: UInt64
149		
150		access(all)
151		let serialNumber: UInt64
152		
153		access(all)
154		view fun getViews(): [Type]{ 
155			return [Type<MetadataViews.Display>(), Type<MetadataViews.Serial>(), Type<MetadataViews.Traits>(), Type<MetadataViews.NFTCollectionData>(), Type<MetadataViews.NFTCollectionDisplay>(), Type<MetadataViews.Royalties>(), Type<MetadataViews.ExternalURL>()]
156		}
157		
158		access(all)
159		fun resolveView(_ view: Type): AnyStruct?{ 
160			switch view{ 
161				case Type<MetadataViews.Display>():
162					return MetadataViews.Display(name: self.getNFTTemplate().name, description: self.getNFTTemplate().description, thumbnail: MetadataViews.HTTPFile(url: self.getNFTTemplate().getMetadata()["uri"]!))
163				case Type<MetadataViews.ExternalURL>():
164					return MetadataViews.ExternalURL("https://www.inceptionanimals.com/")
165				case Type<MetadataViews.Serial>():
166					return MetadataViews.Serial(self.templateID)
167				case Type<MetadataViews.NFTCollectionData>():
168					return MetadataViews.NFTCollectionData(storagePath: InceptionAvatar.CollectionStoragePath, publicPath: InceptionAvatar.CollectionPublicPath, publicCollection: Type<&InceptionAvatar.Collection>(), publicLinkedType: Type<&InceptionAvatar.Collection>(), createEmptyCollectionFunction: fun (): @{NonFungibleToken.Collection}{ 
169							return <-InceptionAvatar.createEmptyCollection(nftType: Type<@InceptionAvatar.Collection>())
170						})
171				case Type<MetadataViews.NFTCollectionDisplay>():
172					let media = MetadataViews.Media(file: MetadataViews.HTTPFile(url: "https://inceptionanimals.com/logo.png"), mediaType: "image/png")
173					return MetadataViews.NFTCollectionDisplay(name: "Inception Animals", description: "A retro futuristic metaverse brand", externalURL: MetadataViews.ExternalURL("https://inceptionanimals.com/"), squareImage: media, bannerImage: media, socials:{ "twitter": MetadataViews.ExternalURL("https://twitter.com/Inceptionft")})
174				case Type<MetadataViews.Traits>():
175					let excludedTraits = ["mintedTime", "foo"]
176					let traitsView = MetadataViews.dictToTraits(dict: (self.getNFTTemplate()!).getMetadata(), excludedNames: excludedTraits)
177					return traitsView
178				case Type<MetadataViews.Royalties>():
179					return MetadataViews.Royalties([])
180			}
181			return nil
182		}
183		
184		access(all)
185		fun getNFTTemplate(): InceptionAvatarTemplate{ 
186			return InceptionAvatar.InceptionAvatarTemplates[self.templateID]!
187		}
188		
189		access(all)
190		fun getNFTMetadata():{ String: String}{ 
191			return (InceptionAvatar.InceptionAvatarTemplates[self.templateID]!).getMetadata()
192		}
193		
194		access(all)
195		fun createEmptyCollection(): @{NonFungibleToken.Collection}{ 
196			return <-create Collection()
197		}
198		
199		init(initID: UInt64, initTemplateID: UInt64, serialNumber: UInt64){ 
200			self.id = initID
201			self.templateID = initTemplateID
202			self.serialNumber = serialNumber
203		}
204	}
205	
206	access(all)
207	resource Collection: InceptionAvatarCollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.Collection, NonFungibleToken.CollectionPublic, ViewResolver.ResolverCollection{ 
208		access(all)
209		var ownedNFTs: @{UInt64:{ NonFungibleToken.NFT}}
210		
211		access(NonFungibleToken.Withdraw)
212		fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT}{ 
213			let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
214			emit Withdraw(id: token.id, from: self.owner?.address)
215			return <-token
216		}
217		
218		access(all)
219		fun deposit(token: @{NonFungibleToken.NFT}): Void{ 
220			let token <- token as! @InceptionAvatar.NFT
221			let id: UInt64 = token.id
222			let oldToken <- self.ownedNFTs[id] <- token
223			emit Deposit(id: id, to: self.owner?.address)
224			destroy oldToken
225		}
226		
227		access(all)
228		fun batchDeposit(collection: @Collection){ 
229			let keys = collection.getIDs()
230			for key in keys{ 
231				self.deposit(token: <-collection.withdraw(withdrawID: key))
232			}
233			destroy collection
234		}
235		
236		access(all)
237		view fun getIDs(): [UInt64]{ 
238			return self.ownedNFTs.keys
239		}
240		
241		access(all)
242		view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}?{ 
243			return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
244		}
245		
246		access(all)
247		fun borrowInceptionAvatar(id: UInt64): &InceptionAvatar.NFT?{ 
248			if self.ownedNFTs[id] != nil{ 
249				let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
250				return ref as! &InceptionAvatar.NFT
251			} else{ 
252				return nil
253			}
254		}
255		
256		access(all)
257		view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}?{ 
258			let nft = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
259			let exampleNFT = nft as! &InceptionAvatar.NFT
260			return exampleNFT as &{ViewResolver.Resolver}
261		}
262		
263		access(all)
264		view fun getSupportedNFTTypes():{ Type: Bool}{ 
265			panic("implement me")
266		}
267		
268		access(all)
269		view fun isSupportedNFTType(type: Type): Bool{ 
270			panic("implement me")
271		}
272		
273		access(all)
274		fun createEmptyCollection(): @{NonFungibleToken.Collection}{ 
275			return <-create Collection()
276		}
277		
278		init(){ 
279			self.ownedNFTs <-{} 
280		}
281	}
282	
283	access(all)
284	fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection}{ 
285		return <-create Collection()
286	}
287	
288	access(all)
289	resource Set{ 
290		access(all)
291		let setID: UInt64
292		
293		access(all)
294		let name: String
295		
296		access(self)
297		var templateIDs: [UInt64]
298		
299		access(self)
300		var availableTemplateIDs: [UInt64]
301		
302		access(self)
303		var lockedTemplates:{ UInt64: Bool}
304		
305		access(all)
306		var locked: Bool
307		
308		access(all)
309		var nextSetSerialNumber: UInt64
310		
311		access(all)
312		var isPublic: Bool
313		
314		init(name: String){ 
315			self.name = name
316			self.setID = InceptionAvatar.nextSetID
317			self.templateIDs = []
318			self.lockedTemplates ={} 
319			self.locked = false
320			self.availableTemplateIDs = []
321			self.nextSetSerialNumber = 1
322			self.isPublic = false
323			InceptionAvatar.nextSetID = InceptionAvatar.nextSetID + 1
324			emit SetCreated(setID: self.setID)
325		}
326		
327		access(all)
328		fun getAvailableTemplateIDs(): [UInt64]{ 
329			return self.availableTemplateIDs
330		}
331		
332		access(all)
333		fun makeSetPublic(){ 
334			self.isPublic = true
335		}
336		
337		access(all)
338		fun makeSetPrivate(){ 
339			self.isPublic = false
340		}
341		
342		access(all)
343		fun addTemplate(templateID: UInt64){ 
344			pre{ 
345				InceptionAvatar.InceptionAvatarTemplates[templateID] != nil:
346					"Template doesn't exist"
347				!self.locked:
348					"Cannot add template - set is locked"
349				!self.templateIDs.contains(templateID):
350					"Cannot add template - template is already added to the set"
351				!((InceptionAvatar.InceptionAvatarTemplates[templateID]!).addedToSet != 0):
352					"Cannot add template - template is already added to another set"
353			}
354			self.templateIDs.append(templateID)
355			self.availableTemplateIDs.append(templateID)
356			self.lockedTemplates[templateID] = false
357			(InceptionAvatar.InceptionAvatarTemplates[templateID]!).markAddedToSet(setID: self.setID)
358			emit TemplateAddedToSet(setID: self.setID, templateID: templateID)
359		}
360		
361		access(all)
362		fun addTemplates(templateIDs: [UInt64]){ 
363			for template in templateIDs{ 
364				self.addTemplate(templateID: template)
365			}
366		}
367		
368		access(all)
369		fun lockTemplate(templateID: UInt64){ 
370			pre{ 
371				self.lockedTemplates[templateID] != nil:
372					"Cannot lock the template: Template is locked already!"
373				!self.availableTemplateIDs.contains(templateID):
374					"Cannot lock a not yet minted template!"
375			}
376			if !self.lockedTemplates[templateID]!{ 
377				self.lockedTemplates[templateID] = true
378				emit TemplateLockedFromSet(setID: self.setID, templateID: templateID)
379			}
380		}
381		
382		access(all)
383		fun lockAllTemplates(){ 
384			for template in self.templateIDs{ 
385				self.lockTemplate(templateID: template)
386			}
387		}
388		
389		access(all)
390		fun lock(){ 
391			if !self.locked{ 
392				self.locked = true
393				emit SetLocked(setID: self.setID)
394			}
395		}
396		
397		access(all)
398		fun mintNFT(): @NFT{ 
399			let templateID = self.availableTemplateIDs[0]
400			if (InceptionAvatar.InceptionAvatarTemplates[templateID]!).locked{ 
401				panic("template is locked")
402			}
403			let newNFT: @NFT <- create InceptionAvatar.NFT(initID: InceptionAvatar.totalSupply, initTemplateID: templateID, serialNumber: self.nextSetSerialNumber)
404			InceptionAvatar.totalSupply = InceptionAvatar.totalSupply + 1
405			self.nextSetSerialNumber = self.nextSetSerialNumber + 1
406			self.availableTemplateIDs.remove(at: 0)
407			emit Minted(id: newNFT.id, templateID: newNFT.getNFTTemplate().templateID)
408			return <-newNFT
409		}
410		
411		access(all)
412		fun updateTemplateMetadata(templateID: UInt64, newMetadata:{ String: String}): InceptionAvatarTemplate{ 
413			pre{ 
414				InceptionAvatar.InceptionAvatarTemplates[templateID] != nil:
415					"Template doesn't exist"
416				!self.locked:
417					"Cannot edit template - set is locked"
418			}
419			(InceptionAvatar.InceptionAvatarTemplates[templateID]!).updateMetadata(newMetadata: newMetadata)
420			emit TemplateUpdated(template: InceptionAvatar.InceptionAvatarTemplates[templateID]!)
421			return InceptionAvatar.InceptionAvatarTemplates[templateID]!
422		}
423	}
424	
425	access(all)
426	resource Admin{ 
427		access(all)
428		fun mintNFT(recipient: &{NonFungibleToken.CollectionPublic}, setID: UInt64){ 
429			let set = self.borrowSet(setID: setID)
430			if (set.getAvailableTemplateIDs()!).length == 0{ 
431				panic("set is empty")
432			}
433			if set.locked{ 
434				panic("set is locked")
435			}
436			recipient.deposit(token: <-set.mintNFT())
437		}
438		
439		access(all)
440		fun createInceptionAvatarTemplate(name: String, description: String, metadata:{ String: String}){ 
441			InceptionAvatar.InceptionAvatarTemplates[InceptionAvatar.nextTemplateID] = InceptionAvatarTemplate(templateID: InceptionAvatar.nextTemplateID, name: name, description: description, metadata: metadata)
442		}
443		
444		access(all)
445		fun createSet(name: String){ 
446			var newSet <- create Set(name: name)
447			InceptionAvatar.sets[newSet.setID] <-! newSet
448		}
449		
450		access(all)
451		fun borrowSet(setID: UInt64): &Set{ 
452			pre{ 
453				InceptionAvatar.sets[setID] != nil:
454					"Cannot borrow Set: The Set doesn't exist"
455			}
456			return (&InceptionAvatar.sets[setID] as &Set?)!
457		}
458		
459		access(all)
460		fun updateInceptionAvatarTemplate(templateID: UInt64, newMetadata:{ String: String}){ 
461			pre{ 
462				InceptionAvatar.InceptionAvatarTemplates.containsKey(templateID) != nil:
463					"Template does not exits."
464			}
465			(InceptionAvatar.InceptionAvatarTemplates[templateID]!).updateMetadata(newMetadata: newMetadata)
466		}
467	}
468	
469	access(all)
470	fun getInceptionAvatarTemplateByID(templateID: UInt64): InceptionAvatar.InceptionAvatarTemplate{ 
471		return InceptionAvatar.InceptionAvatarTemplates[templateID]!
472	}
473	
474	access(all)
475	fun getInceptionAvatarTemplates():{ UInt64: InceptionAvatar.InceptionAvatarTemplate}{ 
476		return InceptionAvatar.InceptionAvatarTemplates
477	}
478	
479	access(all)
480	fun getAvailableTemplateIDsInSet(setID: UInt64): [UInt64]{ 
481		pre{ 
482			InceptionAvatar.sets[setID] != nil:
483				"Cannot borrow Set: The Set doesn't exist"
484		}
485		let set = (&InceptionAvatar.sets[setID] as &Set?)!
486		return set.getAvailableTemplateIDs()
487	}
488
489  	access(all) view fun getContractViews(resourceType: Type?): [Type] {
490		return []
491	}
492
493	access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
494		return nil
495	}
496	
497	init(){ 
498		self.CollectionStoragePath = /storage/InceptionAvatarCollection
499		self.CollectionPublicPath = /public/InceptionAvatarCollection
500		self.AdminStoragePath = /storage/InceptionAvatarAdmin
501		self.totalSupply = 0
502		self.nextTemplateID = 1
503		self.nextSetID = 1
504		self.sets <-{} 
505		self.InceptionAvatarTemplates ={} 
506		let admin <- create Admin()
507		self.account.storage.save(<-admin, to: self.AdminStoragePath)
508		emit ContractInitialized()
509	}
510}
511