Smart Contract
FantastecSwapDataV2
A.4bbff461fa8f6192.FantastecSwapDataV2
1/**
2# Contract: FantastecSwapDataV2
3# Description:
4
5The purpose of this contract is to provide a central location to hold and maintain metadata about Fantastec Swap's Cards and Collections.
6
7Collections represent a themed set of Cards, as indicated on their attributes.
8Collections have 0 or more Cards associated with them.
9Cards represent an individual item or moment of interest - a digital card of a player or stadium, a video moment, a VR scene, or access to other resources.
10An NFT will be minted against individual Card.
11*/
12
13import FantastecSwapDataProperties from 0x4bbff461fa8f6192
14
15access(all) contract FantastecSwapDataV2 {
16
17 access(all) entitlement Owner
18
19 /** EVENTS **/
20 // Contract Events
21 access(all) event ContractInitialized()
22
23 // Card Events
24 access(all) event CardCreated(id: UInt64)
25 access(all) event CardUpdated(id: UInt64)
26 access(all) event CardDeleted(id: UInt64)
27
28 // CardCollection Events
29 access(all) event CardCollectionCreated(id: UInt64)
30 access(all) event CardCollectionUpdated(id: UInt64)
31 access(all) event CardCollectionDeleted(id: UInt64)
32
33 access(all) let AdminStoragePath: StoragePath
34 access(all) let DataStoragePath: StoragePath
35
36 /** CONTRACT LEVEL STRUCTS */
37 access(all) struct CardCollectionData {
38 access(all) let id: UInt64;
39 access(all) var title: String;
40 access(all) var description: String;
41 access(all) var type: String;
42 access(all) var mintVolume: UInt64;
43 access(all) var metadata: {String: [{FantastecSwapDataProperties.MetadataElement}]}
44
45 access(contract) fun save(){
46 FantastecSwapDataV2.getDataManager().setCardCollectionData(self)
47 }
48
49 init(
50 _ id: UInt64,
51 _ title: String,
52 _ description: String,
53 _ type: String,
54 _ mintVolume: UInt64,
55 ){
56 self.id = id;
57 self.title = title;
58 self.description = description;
59 self.type = type;
60 self.mintVolume = mintVolume;
61 self.metadata = {};
62 }
63
64 access(contract) fun addMetadata(
65 _ type: String,
66 _ metadata: {FantastecSwapDataProperties.MetadataElement},
67 ) {
68 if (self.metadata[type] == nil) {
69 self.metadata[type] = []
70 }
71 self.metadata[type] = FantastecSwapDataV2.addToMetadata(type, self.metadata[type]!, metadata)
72 }
73
74 access(contract) fun removeMetadata(
75 _ type: String,
76 _ id: UInt64?,
77 ) {
78 if (self.metadata[type] == nil) {
79 self.metadata[type] = []
80 }
81 self.metadata[type] = FantastecSwapDataV2.removeFromMetadata(type, self.metadata[type]!, id)
82 }
83 }
84
85 access(all) struct CardData {
86 access(all) let id: UInt64;
87 access(all) var name: String;
88 access(all) var type: String;
89 access(all) var aspectRatio: String;
90 access(all) var collectionOrder: UInt32;
91 access(all) var collectionId: UInt64;
92 access(all) var metadata: {String: [{FantastecSwapDataProperties.MetadataElement}]}
93
94 access(contract) fun save(){
95 FantastecSwapDataV2.getDataManager().setCardData(self)
96 }
97
98 access(all) fun copy(): CardData {
99 return CardData(self.id, self.name, self.type, self.aspectRatio, self.collectionOrder, self.collectionId)
100 }
101
102 init(
103 _ id: UInt64,
104 _ name: String,
105 _ type: String,
106 _ aspectRatio: String,
107 _ collectionOrder: UInt32,
108 _ collectionId: UInt64,
109 ){
110 assert(FantastecSwapDataV2.getDataManager().cardCollectionData[collectionId] != nil, message: "cannot create cardData when collection ID does not exist")
111
112 self.id = id;
113 self.name = name;
114 self.type = type;
115 self.aspectRatio = aspectRatio;
116 self.collectionOrder = collectionOrder;
117 self.collectionId = collectionId;
118 self.metadata = {};
119 }
120
121 access(contract) fun addMetadata(
122 _ type: String,
123 _ metadata: {FantastecSwapDataProperties.MetadataElement},
124 ) {
125 if (self.metadata[type] == nil) {
126 self.metadata[type] = []
127 }
128 self.metadata[type] = FantastecSwapDataV2.addToMetadata(type, self.metadata[type]!, metadata)
129 }
130
131 access(contract) fun removeMetadata(
132 _ type: String,
133 _ id: UInt64?,
134 ) {
135 if (self.metadata[type] == nil) {
136 self.metadata[type] = []
137 }
138 self.metadata[type] = FantastecSwapDataV2.removeFromMetadata(type, self.metadata[type]!, id)
139 }
140 }
141
142 access(all) resource Admin {
143 // ------------------------
144 // CardCollection functions
145 // ------------------------
146 access(self) fun getCardCollection(id: UInt64): &CardCollectionData {
147 let cardCollection = FantastecSwapDataV2.getCardCollectionById(id: id)
148 ?? panic("No CardCollection found with id: ".concat(id.toString()))
149 return cardCollection
150 }
151
152 access(Owner) fun addCardCollection(
153 id: UInt64,
154 title: String,
155 description: String,
156 type: String,
157 mintVolume: UInt64,
158 ) {
159
160 var newCardCollection = CardCollectionData(id, title, description, type, mintVolume)
161
162 newCardCollection.save()
163
164 emit CardCollectionCreated(id: newCardCollection.id)
165 }
166
167 access(Owner) fun removeCardCollection(id: UInt64) {
168 FantastecSwapDataV2.getDataManager().removeCardCollectionData(id)
169 emit CardCollectionDeleted(id: id)
170 }
171
172 access(Owner) fun addCardCollectionMetadata(
173 collectionId: UInt64,
174 metadataType: String,
175 metadata: {FantastecSwapDataProperties.MetadataElement},
176 ) {
177 let cardCollection = self.getCardCollection(id: collectionId)
178 cardCollection.addMetadata(metadataType, metadata)
179 cardCollection.save()
180 }
181
182 access(Owner) fun removeCardCollectionMetadata(
183 collectionId: UInt64,
184 metadataType: String,
185 metadataId: UInt64,
186 ) {
187 let cardCollection = self.getCardCollection(id: collectionId)
188 cardCollection.removeMetadata(metadataType, metadataId)
189 cardCollection.save()
190 }
191
192 access(Owner) fun emitCardCollectionUpdated(_ id: UInt64){
193 emit CardCollectionUpdated(id: id)
194 }
195
196 // --------------
197 // Card functions
198 // --------------
199 access(self) fun getCard(id: UInt64): FantastecSwapDataV2.CardData {
200 let card = FantastecSwapDataV2.getCardById(id: id)
201 ?? panic("No Card found with id: ".concat(id.toString()))
202 return card
203 }
204
205 access(Owner) fun addCard(
206 id: UInt64,
207 name: String,
208 type: String,
209 aspectRatio: String,
210 collectionOrder: UInt32,
211 collectionId: UInt64,
212 ) {
213 var newCard: CardData = CardData(id, name, type, aspectRatio, collectionOrder, collectionId)
214
215 newCard.save()
216
217 emit CardCreated(id: newCard.id)
218 }
219
220 access(Owner) fun removeCard(id: UInt64) {
221 FantastecSwapDataV2.getDataManager().removeCardData(id)
222 emit CardDeleted(id: id)
223 }
224
225 access(Owner) fun addCardMetadata(
226 cardId: UInt64,
227 metadataType: String,
228 metadata: {FantastecSwapDataProperties.MetadataElement},
229 ) {
230 let card = self.getCard(id: cardId)
231 card.addMetadata(metadataType, metadata)
232 card.save()
233 }
234
235 access(Owner) fun removeCardMetadata(
236 cardId: UInt64,
237 metadataType: String,
238 metadataId: UInt64,
239 ) {
240 let card = self.getCard(id: cardId)
241 card.removeMetadata(metadataType, metadataId)
242 card.save()
243 }
244 access(Owner) fun emitCardUpdated(_ id: UInt64) {
245 emit CardUpdated(id: id)
246 }
247 }
248
249 access(all) resource DataManager {
250 access(contract) var cardCollectionData: {UInt64: CardCollectionData}
251 access(contract) var cardData: {UInt64: CardData}
252
253 access(contract) fun setCardCollectionData(_ cardCollection: CardCollectionData) {
254 self.cardCollectionData[cardCollection.id] = cardCollection
255 }
256
257 access(contract) fun removeCardCollectionData(_ cardCollectionId: UInt64) {
258 self.cardCollectionData.remove(key: cardCollectionId)
259 }
260
261 access(contract) fun setCardData(_ card: CardData) {
262 self.cardData[card.id] = card
263 }
264
265 access(contract) fun removeCardData(_ cardId: UInt64) {
266 self.cardData.remove(key: cardId)
267 }
268
269 init(_ cardCollectionData: {UInt64: CardCollectionData}, _ cardData: {UInt64: CardData}) {
270 self.cardCollectionData = cardCollectionData
271 self.cardData = cardData
272 }
273 }
274
275 /** PUBLIC GETTING FUNCTIONS */
276 // ------------------------
277 // CardCollection functions
278 // ------------------------
279 access(all) fun getCardCollectionById(id: UInt64): &CardCollectionData? {
280 return self.getDataManager().cardCollectionData[id]
281 }
282
283 access(all) fun getCardCollectionIds(): [UInt64] {
284 var keys:[UInt64] = []
285 for collection in self.getDataManager().cardCollectionData.values {
286 keys.append(collection.id)
287 }
288 return keys;
289 }
290
291 // --------------
292 // Card functions
293 // --------------
294 access(all) fun getAllCards(_ offset: Int?, _ pageSize: Int?): {UInt64: CardData} {
295 let cardIds = self.getCardIds(offset, pageSize)
296 let dataManager = self.getDataManager()
297 let cardsDictionary: {UInt64: FantastecSwapDataV2.CardData} = {}
298 for cardId in cardIds {
299 let data = dataManager.cardData[cardId]!
300 cardsDictionary[cardId] = data.copy()
301 }
302 return cardsDictionary
303 }
304
305 access(all) fun getCardById(id: UInt64): CardData? {
306 if let data = self.getDataManager().cardData[id] {
307 return data.copy()
308 }
309 return nil
310 }
311
312 access(all) fun getCardIds(_ offset: Int?, _ pageSize: Int?): [UInt64] {
313 let cardIds = self.getDataManager().cardData.keys;
314 let ids: [UInt64] = []
315 for id in cardIds {
316 ids.append(id)
317 }
318
319 return FantastecSwapDataV2.paginateIds(ids, offset, pageSize)
320 }
321
322 // -----------------
323 // Utility functions
324 // -----------------
325 access(all) fun join(_ array: [String]): String {
326 var res = ""
327 for string in array {
328 res = res.concat(" ").concat(string)
329 }
330 return res
331 }
332
333 access(all) fun paginateIds(_ ids: [UInt64], _ offset: Int?, _ pageSize: Int?): [UInt64] {
334 let from = offset ?? 0
335 if from >= ids.length {
336 return []
337 }
338 var upTo = from + (pageSize ?? ids.length)
339 if upTo > ids.length {
340 upTo = ids.length
341 }
342 let slice = ids.slice(from: from, upTo: upTo)
343 return slice
344 }
345
346 access(contract) fun addToMetadata(
347 _ type: String,
348 _ metadataArray: [{FantastecSwapDataProperties.MetadataElement}],
349 _ metadata: {FantastecSwapDataProperties.MetadataElement},
350 ): [{FantastecSwapDataProperties.MetadataElement}] {
351 if (FantastecSwapDataProperties.IsArrayMetadataType(type)) {
352 var updatedMetadataArray = FantastecSwapDataV2.removeMetadataElementById(metadataArray, metadata.id)
353 updatedMetadataArray.append(metadata)
354 return updatedMetadataArray
355 } else {
356 if metadataArray.length > 0 {
357 metadataArray.removeFirst()
358 }
359 metadataArray.append(metadata)
360 return metadataArray
361 }
362 }
363
364 access(contract) fun removeFromMetadata(
365 _ type: String,
366 _ metadataArray: [{FantastecSwapDataProperties.MetadataElement}],
367 _ id: UInt64?,
368 ): [{FantastecSwapDataProperties.MetadataElement}] {
369 if (FantastecSwapDataProperties.IsArrayMetadataType(type)) {
370 let updatedMetadataArray = FantastecSwapDataV2.removeMetadataElementById(metadataArray, id!)
371 return updatedMetadataArray
372 } else {
373 let metadataExists = metadataArray.length > 0
374 if (metadataExists) {
375 metadataArray.removeFirst()
376 }
377 return metadataArray
378 }
379 }
380
381 access(all) fun removeMetadataElementById(
382 _ array: [{FantastecSwapDataProperties.MetadataElement}],
383 _ id: UInt64,
384 ): [{FantastecSwapDataProperties.MetadataElement}] {
385 if (array == nil) {
386 return []
387 }
388 var indexToRemove: Int = -1
389 for index, element in array {
390 if (element.id == id) {
391 indexToRemove = index
392 break
393 }
394 }
395 if (indexToRemove > -1) {
396 array.remove(at: indexToRemove)
397 }
398 return array
399 }
400
401 access(contract) fun setAdmin(){
402 let oldAdmin <- self.account.storage.load<@Admin>(from: self.AdminStoragePath)
403 self.account.storage.save<@Admin>(<- create Admin(), to: self.AdminStoragePath)
404 destroy oldAdmin
405 }
406
407 access(contract) fun setDataManager() {
408 let oldDataManager <- self.account.storage.load<@DataManager>(from: self.DataStoragePath)
409 var oldCardCollectionData = oldDataManager?.cardCollectionData ?? {}
410 var oldCardData = oldDataManager?.cardData ?? {}
411 self.account.storage.save<@DataManager>(<- create DataManager(oldCardCollectionData, oldCardData), to: self.DataStoragePath)
412 destroy oldDataManager
413 }
414
415 access(contract) fun getDataManager(): &DataManager {
416 return self.account.storage.borrow<&DataManager>(from: self.DataStoragePath)!
417 }
418
419 init() {
420 // set storage paths and Admin resource
421 self.AdminStoragePath = /storage/FantastecSwapV2Admin
422 self.DataStoragePath = /storage/FantastecSwapV2Data
423
424 self.setAdmin()
425 self.setDataManager()
426
427 emit ContractInitialized()
428 }
429}