Smart Contract

FantastecSwapDataV2

A.4bbff461fa8f6192.FantastecSwapDataV2

Deployed

14h ago
Feb 28, 2026, 02:27:40 AM UTC

Dependents

0 imports
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}