Smart Contract
FantastecNFT
A.4bbff461fa8f6192.FantastecNFT
1import FungibleToken from 0xf233dcee88fe0abe
2import NonFungibleToken from 0x1d7e57aa55817448
3import MetadataViews from 0x1d7e57aa55817448
4import FantastecSwapDataV2 from 0x4bbff461fa8f6192
5import FantastecSwapDataProperties from 0x4bbff461fa8f6192
6import ViewResolver from 0x1d7e57aa55817448
7
8access(all) contract FantastecNFT: NonFungibleToken {
9
10 access(all) entitlement Owner
11
12 // Events
13 //
14 access(all) event ContractInitialized()
15 access(all) event Withdraw(id: UInt64, from: Address?)
16 access(all) event Deposit(id: UInt64, to: Address?)
17 access(all) event Minted(id: UInt64)
18 access(all) event Destroyed(id: UInt64, reason: String)
19
20 // Named Paths
21 //
22 access(all) let CollectionStoragePath: StoragePath
23 access(all) let CollectionPublicPath: PublicPath
24 access(all) let MinterStoragePath: StoragePath
25
26 // totalSupply
27 // The total number of FantastecNFT that have ever been minted
28 access(all) var totalSupply: UInt64
29
30 access(all) struct Item {
31 access(all) let id: UInt64
32 access(all) let cardId: UInt64
33 access(all) let edition: UInt64
34 access(all) let mintNumber: UInt64
35 access(all) let licence: String
36 access(all) let dateMinted: String
37 access(all) let metadata: {String: String}
38 init(
39 id: UInt64,
40 cardId: UInt64,
41 edition: UInt64,
42 mintNumber: UInt64,
43 licence: String,
44 dateMinted: String,
45 metadata: {String: String}){
46 self.id = id
47 self.cardId = cardId
48 self.edition = edition
49 self.mintNumber = mintNumber
50 self.licence = licence
51 self.dateMinted = dateMinted
52 self.metadata = metadata
53 }
54 }
55
56 // NFT: FantastecNFT.NFT
57 // Raw NFT, doesn't currently restrict the caller instantiating an NFT
58 //
59 access(all) resource NFT: NonFungibleToken.NFT {
60 // The token's ID
61 access(all) let id: UInt64
62 access(all) let cardId: UInt64
63 access(all) let edition: UInt64
64 access(all) let mintNumber: UInt64
65 access(all) let licence: String
66 access(all) let dateMinted: String
67 access(all) let metadata: {String: String}
68
69 // initializer
70 //
71 init(item: Item) {
72 self.id = item.id
73 self.cardId = item.cardId
74 self.edition = item.edition
75 self.mintNumber = item.mintNumber
76 self.licence = item.licence
77 self.dateMinted = item.dateMinted
78 self.metadata = item.metadata
79 }
80
81 access(self) fun concatenateStrings(_ strings: [String?]): String {
82 var res = ""
83 for string in strings {
84 if (string != nil) {
85 if (res.length > 0) {
86 res = res.concat(", ")
87 }
88 res = res.concat(string!)
89 }
90 }
91 return res
92 }
93
94 access(self) fun getCard(): FantastecSwapDataV2.CardData? {
95 let card = FantastecSwapDataV2.getCardById(id: self.cardId)
96 return card
97 }
98
99 access(self) fun getCardCollection(): &FantastecSwapDataV2.CardCollectionData? {
100 let card = self.getCard()
101 if (card != nil) {
102 let cardCollection = FantastecSwapDataV2.getCardCollectionById(id: card!.collectionId)
103 return cardCollection
104 }
105 return nil
106 }
107
108 access(self) fun getCardRoyalties(): [MetadataViews.Royalty] {
109 let card = self.getCard()
110 let cardMetadata = card?.metadata ?? {}
111 let royaltiesMetadata = cardMetadata["royalties"]
112 var royalties: [MetadataViews.Royalty] = []
113 if (royaltiesMetadata != nil) {
114 for royaltyElement in royaltiesMetadata! {
115 let royalty = royaltyElement as! FantastecSwapDataProperties.Royalty
116 let receiver = getAccount(royalty.address).capabilities.get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)
117 let cut = royalty.percentage / 100.0
118 let description = royalty.id.toString()
119 royalties.append(
120 MetadataViews.Royalty(receiver: receiver, cut: cut, description: description)
121 )
122 }
123 }
124 return royalties
125 }
126
127 access(self) fun getCardMintVolume(): FantastecSwapDataProperties.MintVolume? {
128 let card = self.getCard()
129 let cardMetadata = card?.metadata ?? {}
130 let mintVolumeMetadata = cardMetadata["mintVolume"]
131 if (mintVolumeMetadata != nil && mintVolumeMetadata!.length > 0) {
132 let mintVolume = mintVolumeMetadata![0] as? FantastecSwapDataProperties.MintVolume
133 return mintVolume
134 }
135 return nil
136 }
137
138 access(self) fun getCardMediaFile(_ mediaType: String): MetadataViews.HTTPFile {
139 let card = self.getCard()
140 let cardMetadata = card?.metadata ?? {}
141 let mediaMetadata = cardMetadata["media"]
142 if (mediaMetadata != nil) {
143 for mediaElement in mediaMetadata! {
144 let media = mediaElement as! FantastecSwapDataProperties.Media
145 if (media.mediaType == mediaType) {
146 return MetadataViews.HTTPFile(url: media.url)
147 }
148 }
149 }
150 return MetadataViews.HTTPFile(url: "")
151 }
152
153 access(self) fun getCardCollectionMediaFile(_ mediaType: String): MetadataViews.HTTPFile {
154 let cardCollection = self.getCardCollection()
155 let cardCollectionMetadata = cardCollection?.metadata ?? &{}
156 let mediaMetadata = cardCollectionMetadata["media"]
157 if (mediaMetadata != nil) {
158 for mediaElement in mediaMetadata! {
159 let media = mediaElement as! FantastecSwapDataProperties.Media
160 if (media.mediaType == mediaType) {
161 return MetadataViews.HTTPFile(url: media.url)
162 }
163 }
164 }
165 return MetadataViews.HTTPFile(url: "")
166 }
167
168 access(self) fun getCardCollectionSocials(): {String: MetadataViews.ExternalURL} {
169 let cardCollection = self.getCardCollection()
170 let cardCollectionMetadata = cardCollection?.metadata ?? &{}
171 let socialsMetadata = cardCollectionMetadata["socials"]
172 var socialsDictionary: {String: MetadataViews.ExternalURL} = {}
173 if (socialsMetadata != nil) {
174 for socialElement in socialsMetadata! {
175 let social = socialElement as! FantastecSwapDataProperties.Social
176 socialsDictionary[social.type] = MetadataViews.ExternalURL(social.url)
177 }
178 }
179 return socialsDictionary
180 }
181
182 access(self) fun getCardCollectionPartner(): FantastecSwapDataProperties.Partner? {
183 let cardCollection = self.getCardCollection()
184 let cardCollectionMetadata = cardCollection?.metadata ?? &{}
185 let partnerMetadata = cardCollectionMetadata["partner"]
186 if (partnerMetadata != nil && partnerMetadata!.length > 0) {
187 let partner = partnerMetadata![0] as? FantastecSwapDataProperties.Partner
188 return partner
189 }
190 return nil
191 }
192
193 access(self) fun getCardCollectionTeam(): FantastecSwapDataProperties.Team? {
194 let cardCollection = self.getCardCollection()
195 let cardCollectionMetadata = cardCollection?.metadata ?? &{}
196 let teamMetadata = cardCollectionMetadata["team"]
197 if (teamMetadata != nil && teamMetadata!.length > 0) {
198 let team = teamMetadata![0] as? FantastecSwapDataProperties.Team
199 return team
200 }
201 return nil
202 }
203
204 access(self) fun getCardCollectionSeason(): FantastecSwapDataProperties.Season? {
205 let cardCollection = self.getCardCollection()
206 let cardCollectionMetadata = cardCollection?.metadata ?? &{}
207 let seasonMetadata = cardCollectionMetadata["season"]
208 if (seasonMetadata != nil && seasonMetadata!.length > 0) {
209 let season = seasonMetadata![0] as? FantastecSwapDataProperties.Season
210 return season
211 }
212 return nil
213 }
214
215 access(self) fun getCardCollectionPlayer(): FantastecSwapDataProperties.Player? {
216 let card = self.getCard()
217 let cardMetadata = card?.metadata ?? {}
218 let playerMetadata = cardMetadata["player"]
219 if (playerMetadata != nil && playerMetadata!.length > 0) {
220 let player = playerMetadata![0] as? FantastecSwapDataProperties.Player
221 return player
222 }
223 return nil
224 }
225
226 access(self) fun getCardCollectionRedeemInfo(): FantastecSwapDataProperties.RedeemInfoV2? {
227 let card = self.getCard()
228 let cardMetadata = card?.metadata ?? {}
229 let redeemInfoMetadata = cardMetadata["redeemInfo"]
230 if (redeemInfoMetadata != nil && redeemInfoMetadata!.length > 0) {
231 let redeemInfo = redeemInfoMetadata![0] as? FantastecSwapDataProperties.RedeemInfoV2
232 return redeemInfo
233 }
234 return nil
235 }
236
237 access(self) fun getNFTCollectionDisplayDescription(): String {
238 let cardCollection = self.getCardCollection()
239 var description = cardCollection?.description
240 if (description == nil) {
241 let season = self.getCardCollectionSeason()
242 let partner = self.getCardCollectionPartner()
243 let team = self.getCardCollectionTeam()
244 let level = self.getNFTLevel()
245 description = self.concatenateStrings([season?.name, partner?.name, team?.name, level?.name])
246 }
247 return description!
248 }
249
250 access(self) fun extractLevelFromMetadata(
251 metadata: &{String: [{FantastecSwapDataProperties.MetadataElement}]}
252 ): FantastecSwapDataProperties.Level? {
253 let levelMetadata = metadata["level"]
254 if (levelMetadata != nil && levelMetadata!.length > 0) {
255 let level = levelMetadata![0] as? FantastecSwapDataProperties.Level
256 return level
257 }
258 return nil
259 }
260
261 access(self) fun getNFTLevel(): FantastecSwapDataProperties.Level? {
262 // If the card has a level, use that - otherwise use the collection level
263 let card = self.getCard()
264 let cardMetadata = card?.metadata ?? {}
265 let ref: &{String: [{FantastecSwapDataProperties.MetadataElement}]} = &cardMetadata
266 var level = self.extractLevelFromMetadata(metadata: ref)
267
268 if (level == nil) {
269 let cardCollection = self.getCardCollection()
270 let cardCollectionMetadata = cardCollection?.metadata ?? &{}
271 level = self.extractLevelFromMetadata(metadata: cardCollectionMetadata)
272 }
273 return level
274 }
275
276 access(self) fun getNFTMintVolume(): UInt64? {
277 // If the card has a mint volume, use that - otherwise use the collection mint volume
278 let cardMintVolume = self.getCardMintVolume()
279 // Card mint volume is stored in metadata
280 if (cardMintVolume != nil) {
281 return cardMintVolume!.value
282 }
283 let cardCollection = self.getCardCollection()
284 if (cardCollection != nil) {
285 return cardCollection!.mintVolume
286 }
287 return nil
288 }
289
290 access(self) fun getTraits(): MetadataViews.Traits {
291 let traits = MetadataViews.dictToTraits(dict: self.metadata, excludedNames: [])
292
293 let dateMintedTrait = MetadataViews.Trait(name: "DateMinted", value: self.dateMinted, displayType: nil, rarity: nil)
294 traits.addTrait(dateMintedTrait)
295
296 let partner = self.getCardCollectionPartner()
297 if (partner != nil) {
298 let partnerTrait = MetadataViews.Trait(name: "Partner", value: partner!.name, displayType: nil, rarity: nil)
299 traits.addTrait(partnerTrait)
300 }
301 let season = self.getCardCollectionSeason()
302 if (season != nil) {
303 let year = season!.startDate.concat("-").concat(season!.endDate)
304 let yearTrait = MetadataViews.Trait(name: "Year", value: year, displayType: nil, rarity: nil)
305 traits.addTrait(yearTrait)
306 }
307 let team = self.getCardCollectionTeam()
308 if (team != nil) {
309 let teamTrait = MetadataViews.Trait(name: "TeamName", value: team!.name, displayType: nil, rarity: nil)
310 traits.addTrait(teamTrait)
311
312 let teamGenderTrait = MetadataViews.Trait(name: "TeamGender", value: team!.gender, displayType: nil, rarity: nil)
313 traits.addTrait(teamGenderTrait)
314 }
315 let player = self.getCardCollectionPlayer()
316 if (player != nil) {
317 let playerNameTrait = MetadataViews.Trait(name: "PlayerName", value: player!.name, displayType: nil, rarity: nil)
318 traits.addTrait(playerNameTrait)
319
320 let playerGenderTrait = MetadataViews.Trait(name: "PlayerGender", value: player!.gender, displayType: nil, rarity: nil)
321 traits.addTrait(playerGenderTrait)
322
323 if (player!.shirtNumber != nil) {
324 let shirtNumberTrait = MetadataViews.Trait(name: "PlayerShirtNumber", value: player!.shirtNumber, displayType: nil, rarity: nil)
325 traits.addTrait(shirtNumberTrait)
326 }
327
328 if (player!.position != nil) {
329 let positionTrait = MetadataViews.Trait(name: "PlayerPosition", value: player!.position, displayType: nil, rarity: nil)
330 traits.addTrait(positionTrait)
331 }
332 }
333 let redeemInfo = self.getCardCollectionRedeemInfo()
334 if (redeemInfo != nil) {
335 let retailerIdTrait = MetadataViews.Trait(name: "RetailerId", value: redeemInfo!.id, displayType: nil, rarity: nil)
336 traits.addTrait(retailerIdTrait)
337
338 let retailerNameTrait = MetadataViews.Trait(name: "RetailerName", value: redeemInfo!.retailerName, displayType: nil, rarity: nil)
339 traits.addTrait(retailerNameTrait)
340
341 let retailerPinHashTrait = MetadataViews.Trait(name: "RetailerPinHash", value: redeemInfo!.retailerPinHash, displayType: nil, rarity: nil)
342 traits.addTrait(retailerPinHashTrait)
343
344 let retailerAddressTrait = MetadataViews.Trait(name: "RetailerAddress", value: redeemInfo!.retailerAddress, displayType: nil, rarity: nil)
345 traits.addTrait(retailerAddressTrait)
346
347 if redeemInfo!.validFrom != nil {
348 let validFromTrait = MetadataViews.Trait(name: "ValidFrom", value: redeemInfo!.validFrom, displayType: nil, rarity: nil)
349 traits.addTrait(validFromTrait)
350 }
351
352 if redeemInfo!.validTo != nil {
353 let validFromTrait = MetadataViews.Trait(name: "ValidTo", value: redeemInfo!.validFrom, displayType: nil, rarity: nil)
354 traits.addTrait(validFromTrait)
355 }
356
357 if redeemInfo!.type != nil {
358 let redeemTypeTrait = MetadataViews.Trait(name: "RedeemType", value: redeemInfo!.type, displayType: nil, rarity: nil)
359 traits.addTrait(redeemTypeTrait)
360 }
361
362 if redeemInfo!.t_and_cs != nil {
363 let tAndCsTrait = MetadataViews.Trait(name: "TAndCs", value: redeemInfo!.t_and_cs, displayType: nil, rarity: nil)
364 traits.addTrait(tAndCsTrait)
365 }
366
367 if redeemInfo!.description != nil {
368 let descriptionTrait = MetadataViews.Trait(name: "Description", value: redeemInfo!.description, displayType: nil, rarity: nil)
369 traits.addTrait(descriptionTrait)
370 }
371 }
372 let card = self.getCard()
373 if (card != nil) {
374 let cardIdTrait = MetadataViews.Trait(name: "CardId", value: card!.id, displayType: nil, rarity: nil)
375 traits.addTrait(cardIdTrait)
376
377 let cardTypeTrait = MetadataViews.Trait(name: "CardType", value: card!.type, displayType: nil, rarity: nil)
378 traits.addTrait(cardTypeTrait)
379
380 let cardAspectRatioTrait = MetadataViews.Trait(name: "CardAspectRatio", value: card!.aspectRatio, displayType: nil, rarity: nil)
381 traits.addTrait(cardAspectRatioTrait)
382
383 let collectionIdTrait = MetadataViews.Trait(name: "CollectionId", value: card!.collectionId, displayType: nil, rarity: nil)
384 traits.addTrait(collectionIdTrait)
385 }
386 let mintVolume = self.getNFTMintVolume()
387 if (mintVolume != nil) {
388 let mintVolumeTrait = MetadataViews.Trait(name: "MintVolume", value: mintVolume!, displayType: nil, rarity: nil)
389 traits.addTrait(mintVolumeTrait)
390 }
391
392 return traits
393 }
394
395 access(all) view fun getViews(): [Type] {
396 return [
397 Type<MetadataViews.Display>(),
398 Type<MetadataViews.Editions>(),
399 Type<MetadataViews.ExternalURL>(),
400 Type<MetadataViews.NFTCollectionData>(),
401 Type<MetadataViews.NFTCollectionDisplay>(),
402 Type<MetadataViews.Serial>(),
403 Type<MetadataViews.Traits>(),
404 Type<MetadataViews.Royalties>()
405 ]
406 }
407
408 access(all) fun resolveView(_ view: Type): AnyStruct? {
409 switch (view) {
410 case Type<MetadataViews.Display>():
411 let card = self.getCard()
412 if (card == nil) {
413 return nil
414 }
415 let name = card!.name
416 let cardCollection = self.getCardCollection()
417 var description = cardCollection != nil ? name.concat(", ").concat(cardCollection!.title) : name
418 let level = self.getNFTLevel()
419 if (level != nil) {
420 description = description.concat(", ").concat(level!.name)
421 }
422 var thumbnail = self.getCardMediaFile("CARD_THUMBNAIL")
423
424 let display = MetadataViews.Display(
425 name: name,
426 description: description,
427 thumbnail: thumbnail
428 )
429 return display
430
431 case Type<MetadataViews.Medias>():
432 let items: [MetadataViews.Media] = []
433 let animation = self.getCardMediaFile("CARD_ANIMATION")
434 if (animation.uri() != "") {
435 let animationMedia = MetadataViews.Media(
436 file: animation,
437 mediaType: "video/mp4"
438 )
439 items.append(animationMedia)
440 }
441 let frame = self.getCardMediaFile("CARD_FRAME")
442 if (frame.uri() != "") {
443 let frameMedia = MetadataViews.Media(
444 file: frame,
445 mediaType: "video/mp4"
446 )
447 items.append(frameMedia)
448 }
449 let image = self.getCardMediaFile("CARD_IMAGE")
450 if (image.uri() != "") {
451 let imageMedia = MetadataViews.Media(
452 file: image,
453 mediaType: "image/png" // TODO: get file extensiuon
454 )
455 items.append(imageMedia)
456 }
457 let thumbnail = self.getCardMediaFile("CARD_THUMBNAIL")
458 if (thumbnail.uri() != "") {
459 let thumbnailMedia = MetadataViews.Media(
460 file: thumbnail,
461 mediaType: "image/jpeg"
462 )
463 items.append(thumbnailMedia)
464 }
465 let medias = MetadataViews.Medias(items)
466 return medias
467
468 case Type<MetadataViews.Editions>():
469 let card = self.getCard()
470 if (card == nil) {
471 return nil
472 }
473 let name = card!.name
474 let number = self.mintNumber
475 let cardCollection = self.getCardCollection()
476 var max: UInt64? = self.getNFTMintVolume() ?? 0
477 if max! < number {
478 max = nil
479 }
480 let editionInfo = MetadataViews.Edition(name: name, number: number, max: max)
481 return MetadataViews.Editions([editionInfo])
482
483 case Type<MetadataViews.ExternalURL>():
484 return MetadataViews.ExternalURL("https://www.fantastec-swap.io/nft/view?id=".concat(self.id.toString()))
485
486 case Type<MetadataViews.NFTCollectionData>():
487 return MetadataViews.NFTCollectionData(
488 storagePath: FantastecNFT.CollectionStoragePath,
489 publicPath: FantastecNFT.CollectionPublicPath,
490 publicCollection: Type<&{FantastecNFT.FantastecNFTCollectionPublic}>(),
491 publicLinkedType: Type<&{FantastecNFT.FantastecNFTCollectionPublic,NonFungibleToken.Collection}>(),
492 createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} {
493 return <- FantastecNFT.createEmptyCollection(nftType: Type<@NFT>())
494 })
495 )
496
497 case Type<MetadataViews.NFTCollectionDisplay>():
498 let cardCollection = self.getCardCollection()
499 let name = cardCollection?.title ?? ""
500 let description = self.getNFTCollectionDisplayDescription()
501 let squareImageMedia = MetadataViews.Media(
502 file: self.getCardCollectionMediaFile("COLLECTION_LOGO_IMAGE"),
503 mediaType: "image/png"
504 )
505 let bannerImageMedia = MetadataViews.Media(
506 file: self.getCardCollectionMediaFile("COLLECTION_HEADER_IMAGE"),
507 mediaType: "image/png"
508 )
509 return MetadataViews.NFTCollectionDisplay(
510 name: name,
511 description: description,
512 externalURL: MetadataViews.ExternalURL(""),
513 squareImage: squareImageMedia,
514 bannerImage: bannerImageMedia,
515 socials: self.getCardCollectionSocials()
516 )
517
518 case Type<MetadataViews.Serial>():
519 return MetadataViews.Serial(self.uuid)
520
521 case Type<MetadataViews.Traits>():
522 return self.getTraits()
523
524 case Type<MetadataViews.Royalties>():
525 return MetadataViews.Royalties(self.getCardRoyalties())
526 }
527
528 return nil
529 }
530
531 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
532 return <- FantastecNFT.createEmptyCollection(nftType: self.getType())
533 }
534 }
535
536 // This is the interface that users can cast their FantastecNFT Collection as
537 // to allow others to deposit FantastecNFTs into their Collection. It also allows for reading
538 // the details of FantastecNFTs in the Collection.
539 access(all) resource interface FantastecNFTCollectionPublic: NonFungibleToken.Collection {
540 access(all) fun deposit(token: @{NonFungibleToken.NFT})
541 access(all) fun borrowFantastecNFT(id: UInt64): &FantastecNFT.NFT? {
542 post {
543 (result == nil) || (result?.id == id):
544 "Cannot borrow FantastecNFT reference: The ID of the returned reference is incorrect"
545 }
546 }
547 }
548
549 // Collection
550 // A collection of Moment NFTs owned by an account
551 //
552 access(all) resource Collection: FantastecNFTCollectionPublic {
553 // dictionary of NFT conforming tokens
554 // NFT is a resource type with an UInt64 ID field
555 // metadataObjs is a dictionary of metadata mapped to NFT IDs
556 //
557 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
558
559 // deposit
560 // Takes a NFT and adds it to the collections dictionary
561 // and adds the ID to the id array
562 //
563 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
564 let token <- token
565
566 let id: UInt64 = token.id
567
568 // add the new token to the dictionary which removes the old one
569 let oldToken <- self.ownedNFTs[id] <- token
570
571 emit Deposit(id: id, to: self.owner?.address)
572
573 if (oldToken != nil){
574 emit Destroyed(id: id, reason: "replaced existing resource with the same id")
575 }
576
577 destroy oldToken
578 }
579
580 // getIDs
581 // Returns an array of the IDs that are in the collection
582 //
583 access(all) view fun getIDs(): [UInt64] {
584 return self.ownedNFTs.keys
585 }
586
587 // borrowNFT
588 // Gets a reference to an NFT in the collection
589 // so that the caller can read its metadata and call its methods
590 //
591 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
592 return &self.ownedNFTs[id]
593 }
594
595 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
596 return {Type<@NFT>(): true}
597 }
598
599 access(all) view fun isSupportedNFTType(type: Type): Bool {
600 return type == Type<@NFT>()
601 }
602
603 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
604 return <- create Collection()
605 }
606
607 // borrowFantastecNFT
608 // Gets a reference to an NFT in the collection as a FantastecNFT,
609 // exposing all of its fields.
610 // This is safe as there are no functions that can be called on the FantastecNFT.
611 //
612 access(all) fun borrowFantastecNFT(id: UInt64): &FantastecNFT.NFT? {
613 if self.ownedNFTs[id] != nil {
614 let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
615 return ref as! &FantastecNFT.NFT
616 }
617
618 return nil
619 }
620
621 // withdraw
622 // Removes an NFT from the collection and moves it to the caller
623 //
624 access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
625 let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
626
627 emit Withdraw(id: token.id, from: self.owner?.address)
628
629 return <-token
630 }
631
632 // initializer
633 //
634 init () {
635 self.ownedNFTs <- {}
636 }
637 }
638
639 // NFTMinter
640 // Resource that an admin or something similar would own to be
641 // able to mint new NFTs
642 //
643 access(all) resource NFTMinter {
644 // Mints a new NFTs
645 // Increments mintNumber
646 // returns the newly minted NFT
647 //
648 access(Owner) fun mintAndReturnNFT(
649 cardId: UInt64,
650 edition: UInt64,
651 mintNumber: UInt64,
652 licence: String,
653 dateMinted: String,
654 metadata: {String: String}): @FantastecNFT.NFT {
655
656 let newId = FantastecNFT.totalSupply + 1
657
658 let nftData: Item = Item(
659 id: FantastecNFT.totalSupply,
660 cardId: cardId,
661 edition: edition,
662 mintNumber: mintNumber,
663 licence: licence,
664 dateMinted: dateMinted,
665 metadata: metadata,
666 )
667 var newNFT <-create FantastecNFT.NFT(item: nftData)
668
669 // emit and update contract
670 emit Minted(id: nftData.id)
671
672 // update contracts
673 FantastecNFT.totalSupply = newId
674
675 return <- newNFT
676 }
677
678 // Mints a new NFTs
679 // Increments mintNumber
680 // deposits the NFT into the recipients collection using their collection reference
681 //
682 access(Owner) fun mintNFT(
683 recipient: &{NonFungibleToken.CollectionPublic},
684 cardId: UInt64,
685 edition: UInt64,
686 mintNumber: UInt64,
687 licence: String,
688 dateMinted: String,
689 metadata: {String: String}) {
690
691 var newNFT <- self.mintAndReturnNFT(
692 cardId: cardId,
693 edition: edition,
694 mintNumber: mintNumber,
695 licence: licence,
696 dateMinted: dateMinted,
697 metadata: metadata
698 )
699
700 // deposit it in the recipient's account using their reference
701 recipient.deposit(token: <- newNFT)
702 }
703 }
704
705 /// Function that resolves a metadata view for this contract.
706 ///
707 /// @param view: The Type of the desired view.
708 /// @return A structure representing the requested view.
709 ///
710 access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
711 switch viewType {
712 case Type<MetadataViews.NFTCollectionData>():
713 return MetadataViews.NFTCollectionData(
714 storagePath: FantastecNFT.CollectionStoragePath,
715 publicPath: FantastecNFT.CollectionPublicPath,
716 publicCollection: Type<&{FantastecNFT.FantastecNFTCollectionPublic}>(),
717 publicLinkedType: Type<&{FantastecNFT.FantastecNFTCollectionPublic}>(),
718 createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} {
719 return <-FantastecNFT.createEmptyCollection(nftType: Type<@NFT>())
720 })
721 )
722 case Type<MetadataViews.NFTCollectionDisplay>():
723 return MetadataViews.NFTCollectionDisplay(
724 name: "Fantastec SWAP",
725 description: "Collect and Swap NFTs created exclusively for European Football clubs Real Madrid Mens and Womens, Arsenal Mens and Womens, Borussia Dortmund, and US College Athletes at Michigan State University, University of Michigan, University of Illinois, and Syracuse University.",
726 externalURL: MetadataViews.ExternalURL("https://fantastec-swap.io"),
727 squareImage: MetadataViews.Media(
728 file: MetadataViews.HTTPFile(
729 url: "https://bafkreihvx3vfgnpn4ygfdcq4w7pdlamw4maasok7xuzcfoutm3lbitwprm.ipfs.nftstorage.link/"
730 ),
731 mediaType: "image/jpeg"
732 ),
733 bannerImage: MetadataViews.Media(
734 file: MetadataViews.HTTPFile(
735 url: "https://bafybeicadjtenkcpdts3rf43a7dgcjjfasihcaed46yxkdgvehj4m33ate.ipfs.nftstorage.link/"
736 ),
737 mediaType: "image/jpeg"
738 ),
739 socials: {
740 "twitter": MetadataViews.ExternalURL("https://twitter.com/fantastecSWAP")
741 }
742 )
743 }
744 return nil
745 }
746
747 /// Function that returns all the Metadata Views implemented by a Non Fungible Token
748 ///
749 /// @return An array of Types defining the implemented views. This value will be used by
750 /// developers to know which parameter to pass to the resolveView() method.
751 ///
752 access(all) view fun getContractViews(resourceType: Type?): [Type] {
753 return [
754 Type<MetadataViews.NFTCollectionData>(),
755 Type<MetadataViews.NFTCollectionDisplay>()
756 ]
757 }
758
759 access(all) fun getTotalSupply(): UInt64 {
760 return FantastecNFT.totalSupply;
761 }
762
763 access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
764 return <- create Collection()
765 }
766
767 init(){
768 // Set our named paths
769 self.CollectionStoragePath = /storage/FantastecNFTCollection
770 self.CollectionPublicPath = /public/FantastecNFTCollection
771 self.MinterStoragePath = /storage/FantastecNFTMinter
772
773 // Initialize the total supply
774 self.totalSupply = 0
775
776 // Create a Minter resource and save it to storage
777 let minter <- create NFTMinter()
778 let oldMinter <- self.account.storage.load<@NFTMinter>(from: self.MinterStoragePath)
779 self.account.storage.save(<-minter, to: self.MinterStoragePath)
780 destroy oldMinter
781
782 emit ContractInitialized()
783 }
784}
785