Smart Contract
MFLPackTemplate
A.8ebcbfd516b1da27.MFLPackTemplate
1/**
2 This contract allows MFL to create and manage packTemplates.
3 A packTemplate is in a way the skeleton of a pack, where, among other things,
4 a max supply and current supply are defined,
5 and whether or not packs linked to a packTemplate can be opened.
6**/
7
8access(all)
9contract MFLPackTemplate {
10
11 // Entitlements
12 access(all)
13 entitlement PackTemplateAdminAction
14
15 // Events
16 access(all)
17 event ContractInitialized()
18
19 access(all)
20 event Minted(id: UInt64)
21
22 access(all)
23 event AllowToOpenPacks(id: UInt64)
24
25 // Named Paths
26 access(all)
27 let PackTemplateAdminStoragePath: StoragePath
28
29 access(all)
30 var nextPackTemplateID: UInt64
31
32 // All packTemplates are stored in this dictionary
33 access(self)
34 let packTemplates: @{UInt64: PackTemplate}
35
36 access(all)
37 struct PackTemplateData {
38 access(all)
39 let id: UInt64
40
41 access(all)
42 let name: String
43
44 access(all)
45 let description: String?
46
47 access(all)
48 let maxSupply: UInt32
49
50 access(all)
51 let currentSupply: UInt32
52
53 access(all)
54 let isOpenable: Bool
55
56 access(all)
57 let imageUrl: String
58
59 access(all)
60 let type: String
61
62 access(contract)
63 let slots: [Slot]
64
65 init(
66 id: UInt64,
67 name: String,
68 description: String?,
69 maxSupply: UInt32,
70 currentSupply: UInt32,
71 isOpenable: Bool,
72 imageUrl: String,
73 type: String,
74 slots: [Slot]
75 ) {
76 self.id = id
77 self.name = name
78 self.description = description
79 self.maxSupply = maxSupply
80 self.currentSupply = currentSupply
81 self.isOpenable = isOpenable
82 self.imageUrl = imageUrl
83 self.type = type
84 self.slots = slots
85 }
86 }
87
88 access(all)
89 struct Slot {
90 access(all)
91 let type: String
92
93 access(contract)
94 let chances: {String: String}
95
96 access(all)
97 let count: UInt32
98
99 init(type: String, chances: {String: String}, count: UInt32) {
100 self.type = type
101 self.chances = chances
102 self.count = count
103 }
104 }
105
106 access(all)
107 resource PackTemplate {
108 access(all)
109 let id: UInt64
110
111 access(contract)
112 let name: String
113
114 access(contract)
115 let description: String?
116
117 access(contract)
118 var maxSupply: UInt32
119
120 access(contract)
121 var currentSupply: UInt32
122
123 access(contract)
124 var isOpenable: Bool
125
126 access(contract)
127 var imageUrl: String
128
129 access(contract)
130 let type: String
131
132 access(contract)
133 let slots: [Slot]
134
135 init(
136 name: String,
137 description: String?,
138 maxSupply: UInt32,
139 imageUrl: String,
140 type: String,
141 slots: [Slot]
142 ) {
143 self.id = MFLPackTemplate.nextPackTemplateID
144 MFLPackTemplate.nextPackTemplateID = MFLPackTemplate.nextPackTemplateID + 1 as UInt64
145 self.name = name
146 self.description = description
147 self.maxSupply = maxSupply
148 self.currentSupply = 0
149 self.isOpenable = false
150 self.imageUrl = imageUrl
151 self.type = type
152 self.slots = slots
153 emit Minted(id: self.id)
154 }
155
156 // Enable accounts to open their packs
157 access(contract)
158 fun allowToOpenPacks() {
159 self.isOpenable = true
160 }
161
162 // Change max supply
163 access(contract)
164 fun updateMaxSupply(maxSupply: UInt32) {
165 assert(maxSupply >= self.currentSupply, message: "Current supply is greater than new max supply")
166
167 self.maxSupply = maxSupply
168 }
169
170 // Increase current supply
171 access(contract)
172 fun increaseCurrentSupply(nbToMint: UInt32) {
173 pre {
174 nbToMint <= self.maxSupply - self.currentSupply:
175 "Supply exceeded"
176 }
177 self.currentSupply = self.currentSupply + nbToMint
178 }
179 }
180
181 // Get all packTemplates IDs
182 access(all)
183 view fun getPackTemplatesIDs(): [UInt64] {
184 return self.packTemplates.keys
185 }
186
187 // Get a data reprensation of a specific packTemplate
188 access(all)
189 fun getPackTemplate(id: UInt64): PackTemplateData? {
190 if let packTemplate = self.getPackTemplateRef(id: id) {
191 let dereferenceSlot = fun (_ slot: Slot): Slot {
192 return slot
193 }
194 return PackTemplateData(
195 id: packTemplate.id,
196 name: packTemplate.name,
197 description: packTemplate.description,
198 maxSupply: packTemplate.maxSupply,
199 currentSupply: packTemplate.currentSupply,
200 isOpenable: packTemplate.isOpenable,
201 imageUrl: packTemplate.imageUrl,
202 type: packTemplate.type,
203 slots: packTemplate.slots.map(dereferenceSlot)
204 )
205 }
206 return nil
207 }
208
209 // Get a data reprensation of all packTemplates
210 access(all)
211 fun getPackTemplates(): [PackTemplateData] {
212 var packTemplatesData: [PackTemplateData] = []
213 for id in self.getPackTemplatesIDs() {
214 if let packTemplate = self.getPackTemplate(id: id) {
215 packTemplatesData.append(packTemplate)
216 }
217 }
218 return packTemplatesData
219 }
220
221 // Get a specif packTemplate ref (in particular for calling admin methods)
222 access(contract)
223 view fun getPackTemplateRef(id: UInt64): &MFLPackTemplate.PackTemplate? {
224 return &self.packTemplates[id] as &MFLPackTemplate.PackTemplate?
225 }
226
227 // Called from MFLPack batchMintPack fct
228 access(account)
229 fun increasePackTemplateCurrentSupply(id: UInt64, nbToMint: UInt32) {
230 let packTemplate = self.getPackTemplateRef(id: id) ?? panic("PackTemplate does not exist")
231 packTemplate.increaseCurrentSupply(nbToMint: nbToMint)
232 }
233
234 // Deprecated: Only here for backward compatibility.
235 access(all)
236 resource interface PackTemplateAdminClaim {}
237
238 access(all)
239 resource PackTemplateAdmin: PackTemplateAdminClaim {
240 access(all)
241 let name: String
242
243 init() {
244 self.name = "PackTemplateAdminClaim"
245 }
246
247 access(PackTemplateAdminAction)
248 fun allowToOpenPacks(id: UInt64) {
249 if let packTemplate = MFLPackTemplate.getPackTemplateRef(id: id) {
250 packTemplate.allowToOpenPacks()
251 emit AllowToOpenPacks(id: id)
252 }
253 }
254
255 access(PackTemplateAdminAction)
256 fun updateMaxSupply(id: UInt64, maxSupply: UInt32) {
257 if let packTemplate = MFLPackTemplate.getPackTemplateRef(id: id) {
258 packTemplate.updateMaxSupply(maxSupply: maxSupply)
259 }
260 }
261
262 access(PackTemplateAdminAction)
263 fun createPackTemplate(name: String, description: String?, maxSupply: UInt32, imageUrl: String, type: String, slots: [Slot]) {
264 let newPackTemplate <- create PackTemplate(name: name, description: description, maxSupply: maxSupply, imageUrl: imageUrl, type: type, slots: slots)
265 let oldPackTemplate <- MFLPackTemplate.packTemplates[newPackTemplate.id] <- newPackTemplate
266 destroy oldPackTemplate
267 }
268 }
269
270 init() {
271 // Set our named paths
272 self.PackTemplateAdminStoragePath = /storage/MFLPackTemplateAdmin
273
274 // Initialize contract fields
275 self.nextPackTemplateID = 1
276 self.packTemplates <-{}
277
278 // Create PackTemplateAdmin resource and save it to storage
279 self.account.storage.save(
280 <-create PackTemplateAdmin(),
281 to: self.PackTemplateAdminStoragePath
282 )
283 emit ContractInitialized()
284 }
285}
286