Smart Contract

FlunksGraduationV2

A.807c3d470888cc48.FlunksGraduationV2

Valid From

86,621,494

Deployed

1w ago
Feb 19, 2026, 10:24:09 AM UTC

Dependents

9 imports
1
2// SPDX-License-Identifier: MIT
3import Flunks from 0x807c3d470888cc48
4import NonFungibleToken from 0x1d7e57aa55817448
5import HybridCustodyHelper from 0x807c3d470888cc48
6import MetadataViews from 0x1d7e57aa55817448
7
8access(all)
9contract FlunksGraduationV2 { 
10	access(all)
11	event ContractInitialized()
12	
13	access(all)
14	event Graduate(address: Address, tokenID: UInt64, templateID: UInt64)
15	
16	access(all)
17	event GraduateTimeUpdate(tokenID: UInt64, time: UInt64)
18	
19	access(all)
20	let AdminStoragePath: StoragePath
21	
22	access(self)
23	var GraduatedFlunks:{ UInt64: Bool}
24	
25	access(self)
26	var tokenIDToUri:{ UInt64: String}
27	
28	access(all) fun graduateFlunk(owner: auth(SaveValue, Capabilities, Storage, BorrowValue) &Account, tokenID: UInt64){ 
29		pre{ 
30			!FlunksGraduationV2.GraduatedFlunks.containsKey(tokenID):
31				"Flunk has already graduated"
32		}
33		
34		// Force re-link collections
35		HybridCustodyHelper.forceRelinkCollections(signer: owner)
36		
37		// Check if owner is the true owner of the NFT
38		let ownerCollectionTokenIds =
39			HybridCustodyHelper.getFlunksTokenIDsFromAllLinkedAccounts(ownerAddress: owner.address)
40		if !ownerCollectionTokenIds.contains(tokenID){ 
41			panic("Not owner")
42		}
43		let trueOwnerAddress =
44			HybridCustodyHelper.getChildAccountAddressHoldingFlunksTokenId(
45				ownerAddress: owner.address,
46				tokenID: tokenID
47			)
48			?? panic("Could not find true owner for specified tokenID")
49		let trueOwnercollection =
50			getAccount(trueOwnerAddress).capabilities.get<&Flunks.Collection>(
51				Flunks.CollectionPublicPath
52			).borrow()
53			?? panic("Could not borrow a reference to the account's NFT collection")
54		let item = trueOwnercollection.borrowNFT(tokenID)
55		let serialView =
56			item?.resolveView(Type<MetadataViews.Serial>())
57			?? panic("Could not get the item's serial view")
58		let serial = serialView as! MetadataViews.Serial?
59		let itemTemplateId = serial?.number ?? 0
60		let itemTemplate = Flunks.getFlunksTemplateByID(templateID: itemTemplateId)
61		
62		// Update the NFT metadata and traits on-chain
63		let admin =
64			self.account.storage.borrow<&Flunks.Admin>(from: Flunks.AdminStoragePath)
65			?? panic("Could not borrow a reference to the Flunks Admin")
66		let adminSet = admin.borrowSet(setID: itemTemplate.addedToSet)
67		let newMetadata = Flunks.getFlunksTemplateByID(templateID: itemTemplateId).getMetadata()
68		if (newMetadata["Type"] ?? "") == "Graduated" {
69			// Already graduated - return early
70			FlunksGraduationV2.GraduatedFlunks[tokenID] = true
71			return
72		}
73		newMetadata["Type"] = "Graduated"
74		newMetadata["pixelUri"] = newMetadata["uri"]
75		newMetadata["uri"] = FlunksGraduationV2.tokenIDToUri[tokenID]!
76		adminSet.updateTemplateMetadata(templateID: itemTemplateId, newMetadata: newMetadata)
77		// Graduate Flunks
78		FlunksGraduationV2.GraduatedFlunks[tokenID] = true
79		emit Graduate(address: owner.address, tokenID: tokenID, templateID: itemTemplateId)
80	}
81	
82	access(all) fun isFlunkGraduated(tokenID: UInt64): Bool{ 
83		return FlunksGraduationV2.GraduatedFlunks[tokenID] ?? false
84	}
85
86	access(all)
87	resource Admin{ 
88		access(all) fun setGraduatedUri(tokenID: UInt64, uri: String){ 
89			if FlunksGraduationV2.GraduatedFlunks.containsKey(tokenID){ 
90				return
91			}
92			FlunksGraduationV2.tokenIDToUri[tokenID] = uri
93		}
94		
95		access(all) fun adminGraduatesForUsers(ownerAddress: Address, templateID: UInt64, tokenID: UInt64){ 
96			// Check if owner is the true owner of the NFT
97			let ownerCollectionTokenIds =
98				HybridCustodyHelper.getFlunksTokenIDsFromAllLinkedAccounts(
99					ownerAddress: ownerAddress
100				)
101			if !ownerCollectionTokenIds.contains(tokenID){ 
102				panic("Not owner")
103			}
104			let trueOwnerAddress =
105				HybridCustodyHelper.getChildAccountAddressHoldingFlunksTokenId(
106					ownerAddress: ownerAddress,
107					tokenID: tokenID
108				)
109				?? panic("Could not find true owner for specified tokenID")
110			let trueOwnercollection =
111				getAccount(trueOwnerAddress).capabilities.get<&Flunks.Collection>(
112					Flunks.CollectionPublicPath
113				).borrow()
114				?? panic("Could not borrow a reference to the account's NFT collection")
115			let item = trueOwnercollection.borrowNFT(tokenID)
116			let serialView =
117				item?.resolveView(Type<MetadataViews.Serial>())
118				?? panic("Could not get the item's serial view")
119			let serial = serialView as! MetadataViews.Serial?
120			let itemTemplateId = serial?.number ?? 0
121			let itemTemplate = Flunks.getFlunksTemplateByID(templateID: itemTemplateId)
122			
123			// Update the NFT metadata and traits on-chain
124			let admin =
125				FlunksGraduationV2.account.storage.borrow<&Flunks.Admin>(
126					from: Flunks.AdminStoragePath
127				)
128				?? panic("Could not borrow a reference to the Flunks Admin")
129			let adminSet = admin.borrowSet(setID: itemTemplate.addedToSet)
130			let newMetadata = Flunks.getFlunksTemplateByID(templateID: itemTemplateId).getMetadata()
131			newMetadata["Type"] = "Graduated"
132			newMetadata["pixelUri"] = newMetadata["uri"]
133			newMetadata["uri"] = FlunksGraduationV2.tokenIDToUri[tokenID]!
134			adminSet.updateTemplateMetadata(templateID: templateID, newMetadata: newMetadata)
135			// Graduate Flunks
136			FlunksGraduationV2.GraduatedFlunks[tokenID] = true
137			emit Graduate(address: ownerAddress, tokenID: tokenID, templateID: templateID)
138		}
139		
140		access(all) fun refreshGraduatedMetadata(ownerAddress: Address, templateID: UInt64, tokenID: UInt64){ 
141			emit Graduate(address: ownerAddress, tokenID: tokenID, templateID: templateID)
142		}
143	}
144	
145	init(){ 
146		self.AdminStoragePath = /storage/FlunksGraduationV2Admin
147		let admin <- create Admin()
148		self.account.storage.save(<-admin, to: self.AdminStoragePath)
149		self.GraduatedFlunks ={} 
150		self.tokenIDToUri ={} 
151		emit ContractInitialized()
152	}
153}
154