Smart Contract
Weekday
A.7752ea736384322f.Weekday
1import TheFabricantMetadataViewsV2 from 0x7752ea736384322f
2
3import ViewResolver from 0x1d7e57aa55817448
4
5import MetadataViews from 0x1d7e57aa55817448
6
7import NonFungibleToken from 0x1d7e57aa55817448
8
9import TheFabricantNFTStandardV2 from 0x7752ea736384322f
10
11import RevealableV2 from 0x7752ea736384322f
12
13import CoCreatableV2 from 0x7752ea736384322f
14
15import TheFabricantAccessList from 0x7752ea736384322f
16
17import FungibleToken from 0xf233dcee88fe0abe
18
19access(all)
20contract Weekday: NonFungibleToken, TheFabricantNFTStandardV2, RevealableV2{
21
22 // -----------------------------------------------------------------------
23 // Paths
24 // -----------------------------------------------------------------------
25 access(all)
26 let WeekdayCollectionStoragePath: StoragePath
27
28 access(all)
29 let WeekdayCollectionPublicPath: PublicPath
30
31 access(all)
32 let WeekdayProviderStoragePath: PrivatePath
33
34 access(all)
35 let WeekdayPublicMinterStoragePath: StoragePath
36
37 access(all)
38 let WeekdayAdminStoragePath: StoragePath
39
40 access(all)
41 let WeekdayPublicMinterPublicPath: PublicPath
42
43 // -----------------------------------------------------------------------
44 // Contract Events
45 // -----------------------------------------------------------------------
46 // Event that emitted when the NFT contract is initialized
47 //
48 access(all)
49 event ContractInitialized()
50
51 access(all)
52 event ItemMintedAndTransferred(uuid: UInt64, id: UInt64, name: String, description: String, collection: String, editionNumber: UInt64, originalRecipient: Address, license: MetadataViews.License?, nftMetadataId: UInt64)
53
54 access(all)
55 event ItemRevealed(uuid: UInt64, id: UInt64, name: String, description: String, collection: String, editionNumber: UInt64, originalRecipient: Address, license: MetadataViews.License?, nftMetadataId: UInt64, externalURL: MetadataViews.ExternalURL, coCreatable: Bool, coCreator: Address)
56
57 access(all)
58 event TraitRevealed(nftUuid: UInt64, id: UInt64, trait: String)
59
60 access(all)
61 event IsTraitRevealableV2Updated(nftUuid: UInt64, id: UInt64, trait: String, isRevealableV2: Bool)
62
63 access(all)
64 event MintPaymentSplitDeposited(address: Address, price: UFix64, amount: UFix64, nftUuid: UInt64)
65
66 access(all)
67 event ItemDestroyed(uuid: UInt64, id: UInt64, name: String, description: String, collection: String)
68
69 access(all)
70 event PublicMinterCreated(uuid: UInt64, name: String, description: String, collection: String, path: String)
71
72 access(all)
73 event PublicMinterIsOpenAccessChanged(uuid: UInt64, name: String, description: String, collection: String, path: String, isOpenAccess: Bool, isAccessListOnly: Bool, isOpen: Bool)
74
75 access(all)
76 event PublicMinterIsAccessListOnly(uuid: UInt64, name: String, description: String, collection: String, path: String, isOpenAccess: Bool, isAccessListOnly: Bool, isOpen: Bool)
77
78 access(all)
79 event PublicMinterMintingIsOpen(uuid: UInt64, name: String, description: String, collection: String, path: String, isOpenAccess: Bool, isAccessListOnly: Bool, isOpen: Bool)
80
81 access(all)
82 event PublicMinterSetAccessListId(uuid: UInt64, name: String, description: String, collection: String, path: String, isOpenAccess: Bool, isAccessListOnly: Bool, isOpen: Bool, accessListId: UInt64)
83
84 access(all)
85 event PublicMinterSetPaymentAmount(uuid: UInt64, name: String, description: String, collection: String, path: String, isOpenAccess: Bool, isAccessListOnly: Bool, isOpen: Bool, paymentAmount: UFix64)
86
87 access(all)
88 event PublicMinterSetMinterMintLimit(uuid: UInt64, name: String, description: String, collection: String, path: String, isOpenAccess: Bool, isAccessListOnly: Bool, isOpen: Bool, minterMintLimit: UInt64?)
89
90 access(all)
91 event AdminResourceCreated(uuid: UInt64, adminAddress: Address)
92
93 access(all)
94 event AdminPaymentReceiverCapabilityChanged(address: Address, paymentType: Type)
95
96 access(all)
97 event AdminSetMaxSupply(maxSupply: UInt64)
98
99 access(all)
100 event AdminSetAddressMintLimit(addressMintLimit: UInt64)
101
102 access(all)
103 event AdminSetCollectionId(collectionId: String)
104
105 access(all)
106 event AdminSetBaseURI(baseURI: String)
107
108 // Event that is emitted when a token is withdrawn,
109 // indicating the owner of the collection that it was withdrawn from.
110 //
111 // If the collection is not in an account's storage, `from` will be `nil`.
112 //
113 access(all)
114 event Withdraw(id: UInt64, from: Address?)
115
116 // Event that emitted when a token is deposited to a collection.
117 //
118 // It indicates the owner of the collection that it was deposited to.
119 //
120 access(all)
121 event Deposit(id: UInt64, to: Address?)
122
123 // -----------------------------------------------------------------------
124 // Contract State
125 // -----------------------------------------------------------------------
126 // NOTE: This is updated anywhere ownership of the nft is changed - on minting and therefore on deposit
127 access(contract)
128 var nftIdsToOwner:{ UInt64: Address}
129
130 access(contract)
131 var publicMinterPaths:{ UInt64: String}
132
133 // NOTE: this is contract-level so all minters can access it.
134 // Keeps track of the number of times an address has minted
135 access(contract)
136 var addressMintCount:{ Address: UInt64}
137
138 // Receives payment for minting
139 access(contract)
140 var paymentReceiverCap: Capability<&{FungibleToken.Receiver}>?
141
142 access(contract)
143 var nftMetadata:{ UInt64:{ RevealableV2.RevealableMetadata}}
144
145 // The total number of tokens of this type in existence
146 // NOTE: All public minters use totalSupply to assign the next
147 // id and edition number. Each public minter has a minterMintLimit property
148 // that defines the max no. of mints a pM can do.
149 access(all)
150 var totalSupply: UInt64
151
152 // NOTE: The max number of NFTs in this collection that will ever be minted
153 // Init as nil if there is no max.
154 access(all)
155 var maxSupply: UInt64?
156
157 // NOTE: Max mints per address
158 access(all)
159 var addressMintLimit: UInt64?
160
161 //NOTE: uuid of collection added to NFT and used by BE
162 access(all)
163 var collectionId: String?
164
165 access(contract)
166 var baseTokenURI: String?
167
168 // -----------------------------------------------------------------------
169 // RevealableV2 Metadata Struct
170 // -----------------------------------------------------------------------
171 access(all)
172 struct RevealableMetadata: RevealableV2.RevealableMetadata{
173
174 //NOTE: totalSupply value of attached NFT, therefore edition number.
175 access(all)
176 let id: UInt64
177
178 // NOTE: !IMPORTANT! nftUuid is the uuid of the associated nft.
179 // This RevealableMetadata struct should be stored in the nftMetadata dict under this
180 // value. This is because the uuid is used across contracts for identification purposes
181 access(all)
182 let nftUuid: UInt64 // uuid of NFT
183
184
185 // NOTE: Name of NFT.
186 // Will be combined with the edition number on the application
187 // Doesn't include the edition number.
188 access(all)
189 var name: String
190
191 access(all)
192 var description: String //Display
193
194
195 // NOTE: Thumbnail, which is needed for the Display view, should be set using one of the
196 // media properties
197 //access(all) let thumbnail: String //Display
198 access(all)
199 let collection: String // Name of collection eg The Fabricant > Season 3 > Wholeland > XXories Originals
200
201
202 // Stores the metadata that describes this particular creation,
203 // but is not part of a characteristic eg mainImage, video etc
204 access(all)
205 var metadata:{ String: AnyStruct}
206
207 // This is where the user-chosed characteristics live. This represents
208 // the data that in older contracts, would've been separate NFTs.
209 access(all)
210 var characteristics:{ String:{ CoCreatableV2.Characteristic}}
211
212 access(all)
213 var rarity: UFix64?
214
215 access(all)
216 var rarityDescription: String?
217
218 // NOTE: Media is not implemented in the struct because MetadataViews.Medias
219 // is not mutable, so can't be updated. In addition, each
220 // NFT collection might have a different number of image/video properties.
221 // Instead, the NFT should implement a function that rolls up the props
222 // into a MetadataViews.Medias struct
223 //access(all) let media: MetadataViews.Medias //Media
224 access(all)
225 let license: MetadataViews.License? //License
226
227
228 access(all)
229 let externalURL: MetadataViews.ExternalURL //ExternalURL
230
231
232 access(all)
233 let coCreatable: Bool
234
235 access(all)
236 let coCreator: Address
237
238 access(all)
239 var isRevealed: Bool?
240
241 // id and editionNumber might not be the same in the nft...
242 access(all)
243 let editionNumber: UInt64 //Edition
244
245
246 access(all)
247 let maxEditionNumber: UInt64?
248
249 access(all)
250 let royalties: MetadataViews.Royalties //Royalty
251
252
253 access(all)
254 let royaltiesTFMarketplace: TheFabricantMetadataViewsV2.Royalties
255
256 access(contract)
257 var revealableTraits:{ String: Bool}
258
259 access(all)
260 fun getRevealableTraits():{ String: Bool}{
261 return self.revealableTraits
262 }
263
264 //NOTE: Customise
265 //NOTE: This should be updated for each campaign contract!
266 // Called by the Admin to reveal the traits for this NFT.
267 // Should contain a switch function that knows how to modify
268 // the properties of this struct. Should check that the trait
269 // being revealed is allowed to be modified.
270 access(contract)
271 fun revealTraits(traits: [{RevealableV2.RevealableTrait}]){
272 //TODO: This is dependent upon what will be saved in this specific campaign
273 // nft.
274 var i = 0
275 while i < traits.length{
276 let RevealableTrait = traits[i]
277 let traitName = RevealableTrait.name
278 let traitValue = RevealableTrait.value
279 switch traitName{
280 case "mainImage":
281 assert(self.checkRevealableTrait(traitName: traitName)!, message: "UnRevealableV2 trait passed in - please ensure trait can be revealed: ".concat(traitName))
282 self.updateMetadata(key: traitName, value: traitValue)
283 case "video":
284 assert(self.checkRevealableTrait(traitName: traitName)!, message: "UnRevealableV2 trait passed in - please ensure trait can be revealed: ".concat(traitName))
285 self.updateMetadata(key: traitName, value: traitValue)
286 default:
287 panic("UnRevealableV2 trait passed in - please ensure trait can be revealed: ".concat(traitName))
288 }
289 i = i + 1
290 }
291 self.isRevealed = true
292 }
293
294 access(contract)
295 fun updateMetadata(key: String, value: AnyStruct){
296 self.metadata[key] = value
297 }
298
299 // Called by the nft owner to modify if a trait can be
300 // revealed or not - used to revoke admin access
301 access(all)
302 fun updateIsTraitRevealable(key: String, value: Bool){
303 self.revealableTraits[key] = value
304 }
305
306 access(all)
307 fun checkRevealableTrait(traitName: String): Bool?{
308 if let RevealableV2 = self.revealableTraits[traitName]{
309 return RevealableV2
310 }
311 return nil
312 }
313
314 init(id: UInt64, nftUuid: UInt64, name: String, description: String, collection: String, metadata:{ String: AnyStruct}, characteristics:{ String:{ CoCreatableV2.Characteristic}}, license: MetadataViews.License?, externalURL: MetadataViews.ExternalURL, coCreatable: Bool, coCreator: Address, editionNumber: UInt64, maxEditionNumber: UInt64?, revealableTraits:{ String: Bool}, royalties: MetadataViews.Royalties, royaltiesTFMarketplace: TheFabricantMetadataViewsV2.Royalties){
315 self.id = id
316 self.nftUuid = nftUuid
317 self.name = name
318 self.description = description
319 self.collection = collection
320 self.metadata = metadata
321 self.characteristics = characteristics
322 self.rarity = nil
323 self.rarityDescription = nil
324 self.license = license
325 self.externalURL = externalURL
326 self.coCreatable = coCreatable
327 self.coCreator = coCreator
328 //NOTE: Customise
329 // This should be nil if the nft can't be revealed!
330 self.isRevealed = true
331 self.editionNumber = editionNumber
332 self.maxEditionNumber = maxEditionNumber
333 self.revealableTraits = revealableTraits
334 self.royalties = royalties
335 self.royaltiesTFMarketplace = royaltiesTFMarketplace
336 }
337 }
338
339 // -----------------------------------------------------------------------
340 // Trait Struct
341 // -----------------------------------------------------------------------
342 // Used by txs to target traits/characteristics to be revealed
343 access(all)
344 struct Trait: RevealableV2.RevealableTrait{
345 access(all)
346 let name: String
347
348 access(all)
349 let value: AnyStruct
350
351 init(name: String, value: AnyStruct){
352 self.name = name
353 self.value = value
354 }
355 }
356
357 // -----------------------------------------------------------------------
358 // NFT Resource
359 // -----------------------------------------------------------------------
360 // Restricted scope for borrowWeekday() in Collection.
361 // Ensures that the returned NFT ref is read only.
362 access(all)
363 resource interface PublicNFT{
364 access(all)
365 fun getFullName(): String
366
367 access(all)
368 fun getEditions(): MetadataViews.Editions
369
370 access(all)
371 fun getMedias(): MetadataViews.Medias
372
373 access(all)
374 fun getTraits(): MetadataViews.Traits?
375
376 access(all)
377 view fun getRarity(): MetadataViews.Rarity?
378
379 access(all)
380 fun getExternalRoyalties(): MetadataViews.Royalties
381
382 access(all)
383 fun getTFRoyalties(): TheFabricantMetadataViewsV2.Royalties
384
385 access(all)
386 fun getMetadata():{ String: AnyStruct}
387
388 access(all)
389 fun getCharacteristics():{ String:{ CoCreatableV2.Characteristic}}?
390
391 access(all)
392 fun getDisplay(): MetadataViews.Display
393
394 access(all)
395 fun getCollectionData(): MetadataViews.NFTCollectionData
396
397 access(all)
398 fun getCollectionDisplay(): MetadataViews.NFTCollectionDisplay
399
400 access(all)
401 fun getNFTView(): MetadataViews.NFTView
402
403 access(all)
404 fun getViews(): [Type]
405
406 access(all)
407 fun resolveView(_ view: Type): AnyStruct?
408 }
409
410 access(all)
411 resource NFT: TheFabricantNFTStandardV2.TFNFT, NonFungibleToken.NFT, ViewResolver.Resolver, PublicNFT{
412 access(all)
413 let id: UInt64
414
415 // NOTE: Ensure that the name for the nft is correct. This
416 // will be shown to users. It should not include the edition number.
417 access(contract)
418 let collectionId: String
419
420 access(contract)
421 let editionNumber: UInt64 //Edition
422
423
424 access(contract)
425 let maxEditionNumber: UInt64?
426
427 access(contract)
428 let originalRecipient: Address
429
430 access(contract)
431 let license: MetadataViews.License?
432
433 access(contract)
434 let nftMetadataId: UInt64
435
436 access(all)
437 fun getFullName(): String{
438 return ((Weekday.nftMetadata[self.nftMetadataId]!).name!).concat(" #".concat(self.editionNumber.toString()))
439 }
440
441 // NOTE: This is important for Edition view
442 access(all)
443 fun getEditionName(): String{
444 return (Weekday.nftMetadata[self.nftMetadataId]!).collection
445 }
446
447 access(all)
448 fun getEditions(): MetadataViews.Editions{
449 // NOTE: In this case, id == edition number
450 let edition = MetadataViews.Edition(name: (Weekday.nftMetadata[self.nftMetadataId]!).collection, number: self.editionNumber, max: Weekday.maxSupply)
451 return MetadataViews.Editions([edition])
452 }
453
454 //NOTE: Customise
455 //NOTE: This will be different for each campaign, determined by how
456 // many media files there are and their keys in metadata! Pay attention
457 // to where the media files are stored and therefore accessed
458 access(all)
459 fun getMedias(): MetadataViews.Medias{
460 let nftMetadata = Weekday.nftMetadata[self.id]!
461 let mainImage = nftMetadata.metadata["mainImage"]! as! String
462 // NOTE: This assumes that when the shoeShape characteristic is created
463 // in the update_shoe_shapes_char tx, the value property is created as a dictionary
464 let video = nftMetadata.metadata["video"]! as! String
465 let mainImageMedia = MetadataViews.Media(file: MetadataViews.HTTPFile(url: mainImage), mediaType: "image/png")
466 let videoMedia = MetadataViews.Media(file: MetadataViews.HTTPFile(url: video), mediaType: "video/mp4")
467 return MetadataViews.Medias([mainImageMedia, videoMedia])
468 }
469
470 // NOTE: Customise
471 access(all)
472 fun getImages():{ String: String}{
473 let nftMetadata = Weekday.nftMetadata[self.id]!
474 let mainImage = nftMetadata.metadata["mainImage"]! as! String
475 return{ "mainImage": mainImage}
476 }
477
478 // NOTE: Customise
479 access(all)
480 fun getVideos():{ String: String}{
481 let nftMetadata = Weekday.nftMetadata[self.id]!
482 let mainVideo = nftMetadata.metadata["video"]! as! String
483 return{ "mainVideo": mainVideo}
484 }
485
486 // NOTE: Customise
487 // What are the traits that you want external marketplaces
488 // to display?
489 access(all)
490 fun getTraits(): MetadataViews.Traits?{
491 return nil
492 }
493
494 access(all)
495 view fun getRarity(): MetadataViews.Rarity?{
496 return nil
497 }
498
499 access(all)
500 fun getExternalRoyalties(): MetadataViews.Royalties{
501 let nftMetadata = Weekday.nftMetadata[self.id]!
502 return nftMetadata.royalties
503 }
504
505 access(all)
506 fun getTFRoyalties(): TheFabricantMetadataViewsV2.Royalties{
507 let nftMetadata = Weekday.nftMetadata[self.id]!
508 return nftMetadata.royaltiesTFMarketplace
509 }
510
511 access(all)
512 fun getMetadata():{ String: AnyStruct}{
513 return (Weekday.nftMetadata[self.id]!).metadata
514 }
515
516 //NOTE: This is not a CoCreatableV2 NFT, so no characteristics are present
517 access(all)
518 fun getCharacteristics():{ String:{ CoCreatableV2.Characteristic}}?{
519 return nil
520 }
521
522 access(all)
523 fun getRevealableTraits():{ String: Bool}?{
524 return (Weekday.nftMetadata[self.id]!).getRevealableTraits()
525 }
526
527 //NOTE: The first file in medias will be the thumbnail.
528 // Maybe put a file type check in here to ensure it is
529 // an image?
530 access(all)
531 fun getDisplay(): MetadataViews.Display{
532 return MetadataViews.Display(name: self.getFullName(), description: (Weekday.nftMetadata[self.nftMetadataId]!).description, thumbnail: self.getMedias().items[0].file)
533 }
534
535 access(all)
536 fun getCollectionData(): MetadataViews.NFTCollectionData{
537 return MetadataViews.NFTCollectionData(storagePath: Weekday.WeekdayCollectionStoragePath, publicPath: Weekday.WeekdayCollectionPublicPath, publicCollection: Type<&Weekday.Collection>(), publicLinkedType: Type<&Weekday.Collection>(), createEmptyCollectionFunction: fun (): @{NonFungibleToken.Collection}{
538 return <-Weekday.createEmptyCollection(nftType: Type<@Weekday.Collection>())
539 })
540 }
541
542 //NOTE: Customise
543 // NOTE: Update this function with the collection display image
544 // and TF socials
545 access(all)
546 fun getCollectionDisplay(): MetadataViews.NFTCollectionDisplay{
547 let squareImage = MetadataViews.Media(file: MetadataViews.HTTPFile(url: "https://weekday-collection-display.s3.eu-central-1.amazonaws.com/images/WD_squareImage.png"), mediaType: "image/png")
548 let bannerImage = MetadataViews.Media(file: MetadataViews.HTTPFile(url: "https://weekday-collection-display.s3.eu-central-1.amazonaws.com/images/WD_bannerImage.jpeg"), mediaType: "image/png")
549 return MetadataViews.NFTCollectionDisplay(name: self.getEditionName(), description: "Enter Artifact 001, a limited-edition collection of digital collectibles complete with AR filters, and physical accessories for the citizens of tomorrow. The items, inspired by mineral formations, are part of a collab between Weekday and digital fashion house The Fabricant. Consider them locked in time, always remaining as they find their way to new owners. Make your move now, history doesn\u{2019}t wait.", externalURL: (Weekday.nftMetadata[self.id]!).externalURL, squareImage: squareImage, bannerImage: bannerImage, socials:{ "twitter": MetadataViews.ExternalURL("https://twitter.com/thefabricant"), "instagram": MetadataViews.ExternalURL("https://www.instagram.com/the_fab_ric_ant/"), "facebook": MetadataViews.ExternalURL("https://www.facebook.com/thefabricantdesign/"), "artstation": MetadataViews.ExternalURL("https://www.artstation.com/thefabricant"), "behance": MetadataViews.ExternalURL("https://www.behance.net/thefabricant"), "linkedin": MetadataViews.ExternalURL("https://www.linkedin.com/company/the-fabricant"), "sketchfab": MetadataViews.ExternalURL("https://sketchfab.com/thefabricant"), "clolab": MetadataViews.ExternalURL("https://www.clo3d.com/en/clollab/thefabricant"), "tiktok": MetadataViews.ExternalURL("@digital_fashion"), "discord": MetadataViews.ExternalURL("https://discord.com/channels/692039738751713280/778601303013195836")})
550 }
551
552 access(all)
553 fun getNFTView(): MetadataViews.NFTView{
554 return MetadataViews.NFTView(id: self.id, uuid: self.uuid, display: self.getDisplay(), externalURL: (Weekday.nftMetadata[self.id]!).externalURL, collectionData: self.getCollectionData(), collectionDisplay: self.getCollectionDisplay(), royalties: (Weekday.nftMetadata[self.id]!).royalties, traits: self.getTraits())
555 }
556
557 access(all)
558 view fun getViews(): [Type]{
559 let viewArray: [Type] = [Type<TheFabricantMetadataViewsV2.TFNFTIdentifierV1>(), Type<TheFabricantMetadataViewsV2.TFNFTSimpleView>(), Type<MetadataViews.NFTView>(), Type<MetadataViews.Display>(), Type<MetadataViews.Editions>(), Type<MetadataViews.Serial>(), Type<MetadataViews.Royalties>(), Type<MetadataViews.Medias>(), Type<MetadataViews.ExternalURL>(), Type<MetadataViews.NFTCollectionData>(), Type<MetadataViews.NFTCollectionDisplay>(), Type<MetadataViews.Traits>()]
560 return viewArray
561 }
562
563 access(all)
564 fun resolveView(_ view: Type): AnyStruct?{
565 switch view{
566 case Type<TheFabricantMetadataViewsV2.TFNFTIdentifierV1>():
567 return TheFabricantMetadataViewsV2.TFNFTIdentifierV1(uuid: self.uuid, id: self.id, name: self.getFullName(), collection: (Weekday.nftMetadata[self.nftMetadataId]!).collection, editions: self.getEditions(), address: (self.owner!).address, originalRecipient: self.originalRecipient)
568 case Type<TheFabricantMetadataViewsV2.TFNFTSimpleView>():
569 return TheFabricantMetadataViewsV2.TFNFTSimpleView(uuid: self.uuid, id: self.id, name: self.getFullName(), description: (Weekday.nftMetadata[self.nftMetadataId]!).description, collection: (Weekday.nftMetadata[self.nftMetadataId]!).collection, collectionId: Weekday.collectionId!, metadata: self.getMetadata(), media: self.getMedias(), images: self.getImages(), videos: self.getVideos(), externalURL: (Weekday.nftMetadata[self.id]!).externalURL, rarity: self.getRarity(), traits: self.getTraits(), characteristics: self.getCharacteristics(), coCreatable: (Weekday.nftMetadata[self.id]!).coCreatable, coCreator: (Weekday.nftMetadata[self.id]!).coCreator, isRevealed: (Weekday.nftMetadata[self.id]!).isRevealed, editions: self.getEditions(), originalRecipient: self.originalRecipient, royalties: (Weekday.nftMetadata[self.id]!).royalties, royaltiesTFMarketplace: (Weekday.nftMetadata[self.id]!).royaltiesTFMarketplace, revealableTraits: self.getRevealableTraits(), address: (self.owner!).address)
570 case Type<MetadataViews.NFTView>():
571 return self.getNFTView()
572 case Type<MetadataViews.Display>():
573 return self.getDisplay()
574 case Type<MetadataViews.Editions>():
575 return self.getEditions()
576 case Type<MetadataViews.Serial>():
577 return self.id
578 case Type<MetadataViews.Royalties>():
579 return Weekday.nftMetadata[self.id]?.royalties
580 case Type<MetadataViews.Medias>():
581 return self.getMedias()
582 case Type<MetadataViews.License>():
583 return self.license
584 case Type<MetadataViews.ExternalURL>():
585 return Weekday.nftMetadata[self.id]?.externalURL
586 case Type<MetadataViews.NFTCollectionData>():
587 return self.getCollectionData()
588 case Type<MetadataViews.NFTCollectionDisplay>():
589 return self.getCollectionDisplay()
590 case Type<MetadataViews.Rarity>():
591 return self.getRarity()
592 case Type<MetadataViews.Traits>():
593 return self.getTraits()
594 }
595 return nil
596 }
597
598 access(all)
599 fun updateIsTraitRevealable(key: String, value: Bool){
600 let nftMetadata = Weekday.nftMetadata[self.id]!
601 nftMetadata.updateIsTraitRevealable(key: key, value: value)
602 Weekday.nftMetadata[self.id] = nftMetadata
603 emit IsTraitRevealableV2Updated(nftUuid: nftMetadata.nftUuid, id: nftMetadata.id, trait: key, isRevealableV2: value)
604 }
605
606 access(all)
607 fun createEmptyCollection(): @{NonFungibleToken.Collection}{
608 return <-create Collection()
609 }
610
611 init(originalRecipient: Address, license: MetadataViews.License?){
612 assert(Weekday.collectionId != nil, message: "Ensure that Admin has set collectionId in the contract")
613 Weekday.totalSupply = Weekday.totalSupply + 1
614 self.id = Weekday.totalSupply
615 self.collectionId = Weekday.collectionId!
616
617 // NOTE: Customise
618 // The edition number may need to be different to id
619 // for some campaigns
620 self.editionNumber = self.id
621 self.maxEditionNumber = Weekday.maxSupply
622 self.originalRecipient = originalRecipient
623 self.license = license
624 self.nftMetadataId = self.id
625 }
626 }
627
628 // -----------------------------------------------------------------------
629 // Collection Resource
630 // -----------------------------------------------------------------------
631 access(all)
632 resource interface WeekdayCollectionPublic{
633 access(all)
634 fun borrowWeekday(id: UInt64): &Weekday.NFT?
635
636 access(all)
637 fun deposit(token: @{NonFungibleToken.NFT})
638
639 access(all)
640 fun getIDs(): [UInt64]
641
642 access(all)
643 view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}?
644
645 access(all)
646 view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}?
647 }
648
649 access(all)
650 resource Collection: NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.Collection, NonFungibleToken.CollectionPublic, WeekdayCollectionPublic, ViewResolver.ResolverCollection{
651
652 // Dictionary to hold the NFTs in the Collection
653 access(all)
654 var ownedNFTs: @{UInt64:{ NonFungibleToken.NFT}}
655
656 access(all)
657 view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}?{
658 let nft = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
659 let Weekday = nft as! &Weekday.NFT
660 return Weekday as &{ViewResolver.Resolver}
661 }
662
663 // withdraw removes an NFT from the collection and moves it to the caller
664 access(NonFungibleToken.Withdraw)
665 fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT}{
666 // Remove the nft from the Collection
667 let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("Cannot withdraw: NFT does not exist in the collection")
668 emit Withdraw(id: token.id, from: self.owner?.address)
669
670 // Return the withdrawn token
671 return <-token
672 }
673
674 // deposit takes an NFT and adds it to the collections dictionary
675 // and adds the ID to the id array
676 access(all)
677 fun deposit(token: @{NonFungibleToken.NFT}){
678 // By ensuring self.owner.address is not nil we keep the nftIdsToOwner dict
679 // up to date.
680 pre{
681 self.owner?.address != nil:
682 "The Collection resource must be stored in a users account"
683 }
684
685 // Cast the deposited token as NFT to make sure
686 // it is the correct type
687 let token <- token as! @NFT
688
689 // Get the token's ID
690 let id = token.id
691
692 // Add the new token to the dictionary
693 let oldToken <- self.ownedNFTs[id] <- token
694 Weekday.nftIdsToOwner[id] = (self.owner!).address
695 emit Deposit(id: id, to: self.owner?.address)
696
697 // Destroy the empty old token that was "removed"
698 destroy oldToken
699 }
700
701 // getIDs returns an array of the IDs that are in the collection
702 access(all)
703 view fun getIDs(): [UInt64]{
704 return self.ownedNFTs.keys
705 }
706
707 // Returns a borrowed reference to an NFT in the collection
708 // so that the caller can read data and call methods from it
709 access(all)
710 view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}?{
711 return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
712 }
713
714 access(all)
715 fun borrowWeekday(id: UInt64): &Weekday.NFT?{
716 if self.ownedNFTs[id] != nil{
717 // Create an authorized reference to allow downcasting
718 let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
719 return ref as! &Weekday.NFT
720 }
721 return nil
722 }
723
724 access(all)
725 view fun getSupportedNFTTypes():{ Type: Bool}{
726 panic("implement me")
727 }
728
729 access(all)
730 view fun isSupportedNFTType(type: Type): Bool{
731 panic("implement me")
732 }
733
734 access(all)
735 fun createEmptyCollection(): @{NonFungibleToken.Collection}{
736 return <-create Collection()
737 }
738
739 // If a transaction destroys the Collection object,
740 // All the NFTs contained within are also destroyed!
741 //
742 init(){
743 self.ownedNFTs <-{}
744 }
745 }
746
747 // -----------------------------------------------------------------------
748 // Admin Resource
749 // -----------------------------------------------------------------------
750 access(all)
751 resource Admin{
752 access(all)
753 fun setPublicReceiverCap(paymentReceiverCap: Capability<&{FungibleToken.Receiver}>){
754 Weekday.paymentReceiverCap = paymentReceiverCap
755 emit AdminPaymentReceiverCapabilityChanged(address: paymentReceiverCap.address, paymentType: paymentReceiverCap.getType())
756 }
757
758 access(all)
759 fun setBaseURI(baseURI: String){
760 Weekday.baseTokenURI = baseURI
761 emit AdminSetBaseURI(baseURI: baseURI)
762 }
763
764 // The max supply determines the maximum number of NFTs that can be minted from this contract
765 access(all)
766 fun setMaxSupply(maxSupply: UInt64){
767 Weekday.maxSupply = maxSupply
768 emit AdminSetMaxSupply(maxSupply: maxSupply)
769 }
770
771 access(all)
772 fun setAddressMintLimit(addressMintLimit: UInt64){
773 Weekday.addressMintLimit = addressMintLimit
774 emit AdminSetAddressMintLimit(addressMintLimit: addressMintLimit)
775 }
776
777 access(all)
778 fun setCollectionId(collectionId: String){
779 Weekday.collectionId = collectionId
780 emit AdminSetCollectionId(collectionId: collectionId)
781 }
782
783 //NOTE: Customise
784 // mint not:
785 // maxSupply has been hit √
786 // minting isn't open (!isOpen) √
787 // mint if:
788 // openAccess √
789 // OR address on access list √
790 // Output:
791 // NFT √
792 // nftMetadata √
793 // update mints per address √
794 //NOTE: !Used for CC payments via MoonPay!
795 access(all)
796 fun distributeDirectlyViaAccessList(receiver: &{NonFungibleToken.CollectionPublic}, publicMinterPathString: String, variantId: UInt64){
797
798 // Ensure that the maximum supply of nfts for this contract has not been hit
799 if Weekday.maxSupply != nil{
800 assert(Weekday.totalSupply + 1 <= Weekday.maxSupply!, message: "Max supply for NFTs has been hit")
801 }
802
803 // Get the publicMinter details so we can apply all the correct props to the NFT
804 //NOTE: Therefore relies on a pM having been created
805 let publicPath = PublicPath(identifier: publicMinterPathString) ?? panic("Failed to construct public path from path string: ".concat(publicMinterPathString))
806 let publicMinterCap = getAccount((self.owner!).address).capabilities.get<&Weekday.PublicMinter>(publicPath).borrow() ?? panic("Couldn't get publicMinter ref or pathString is wrong: ".concat(publicMinterPathString))
807 let publicMinterDetails = publicMinterCap.getPublicMinterDetails()
808
809 //Confirm that minting is open on the publicMinter
810 let isOpen = publicMinterDetails["isOpen"] as! Bool?
811 assert(isOpen!, message: "Minting is not open!")
812
813 //Check that the address has access via the access list. If isOpenAccess, then anyone can mint.
814 let isOpenAccess = publicMinterDetails["isOpenAccess"] as! Bool?
815 let accessListId = publicMinterDetails["accessListId"] as! UInt64?
816 if !isOpenAccess!{
817 assert(TheFabricantAccessList.checkAccessForAddress(accessListDetailsId: accessListId!, address: (receiver.owner!).address), message: "User address is not on the access list and so cannot mint.")
818 }
819
820 // Create the NFT
821 let license = publicMinterDetails["license"] as! MetadataViews.License?
822 let nft <- create NFT(originalRecipient: (receiver.owner!).address, license: license)
823 let name = publicMinterDetails["name"] as! String?
824 let description = publicMinterDetails["description"] as! String?
825 let collection = publicMinterDetails["collection"] as! String?
826 let externalURL = publicMinterDetails["externalURL"] as! MetadataViews.ExternalURL?
827 let coCreatable = publicMinterDetails["coCreatable"] as! Bool?
828 let revealableTraits = publicMinterDetails["revealableTraits"] as!{ String: Bool}?
829 let royalties = publicMinterDetails["royalties"] as! MetadataViews.Royalties?
830 let royaltiesTFMarketplace = publicMinterDetails["royaltiesTFMarketplace"] as! TheFabricantMetadataViewsV2.Royalties?
831
832 //Create the nftMetadata
833 Weekday.createNftMetadata(id: nft.id, nftUuid: nft.uuid, variantId: variantId, name: name!, description: description!, collection: collection!, characteristics:{} , license: nft.license, externalURL: externalURL!, coCreatable: coCreatable!, coCreator: (receiver.owner!).address, editionNumber: nft.editionNumber, maxEditionNumber: nft.maxEditionNumber, revealableTraits: revealableTraits!, royalties: royalties!, royaltiesTFMarketplace: royaltiesTFMarketplace!)
834
835 //NOTE: Event is emitted here and not in nft init because
836 // data is split between RevealableMetadata and nft,
837 // so not all event data is accessible during nft init
838 emit ItemMintedAndTransferred(uuid: nft.uuid, id: nft.id, name: (Weekday.nftMetadata[nft.nftMetadataId]!).name, description: (Weekday.nftMetadata[nft.nftMetadataId]!).description, collection: (Weekday.nftMetadata[nft.nftMetadataId]!).collection, editionNumber: nft.editionNumber, originalRecipient: nft.originalRecipient, license: nft.license, nftMetadataId: nft.nftMetadataId)
839 receiver.deposit(token: <-nft)
840
841 // Increment the number of mints that an address has
842 if Weekday.addressMintCount[(receiver.owner!).address] != nil{
843 Weekday.addressMintCount[(receiver.owner!).address] = Weekday.addressMintCount[(receiver.owner!).address]! + 1
844 } else{
845 Weekday.addressMintCount[(receiver.owner!).address] = 1
846 }
847 }
848
849 // NOTE: It is in the public minter that you would create the restrictions
850 // for minting.
851 access(all)
852 fun createPublicMinter(name: String, description: String, collection: String, license: MetadataViews.License?, externalURL: MetadataViews.ExternalURL, coCreatable: Bool, revealableTraits:{ String: Bool}, minterMintLimit: UInt64?, royalties: MetadataViews.Royalties, royaltiesTFMarketplace: TheFabricantMetadataViewsV2.Royalties, paymentAmount: UFix64, paymentType: Type, paymentSplit: MetadataViews.Royalties?, typeRestrictions: [Type], accessListId: UInt64){
853 pre{
854 Weekday.paymentReceiverCap != nil:
855 "Please set the paymentReceiverCap before creating a minter"
856 }
857 let publicMinter: @Weekday.PublicMinter <- create PublicMinter(name: name, description: description, collection: collection, license: license, externalURL: externalURL, coCreatable: coCreatable, revealableTraits: revealableTraits, minterMintLimit: minterMintLimit, royalties: royalties, royaltiesTFMarketplace: royaltiesTFMarketplace, paymentAmount: paymentAmount, paymentType: paymentType, paymentSplit: paymentSplit, typeRestrictions: typeRestrictions, accessListId: accessListId)
858
859 // Save path: name_collection_uuid
860 // Link the Public Minter to a Public Path of the admin account
861 let publicMinterStoragePath = StoragePath(identifier: publicMinter.path)
862 let publicMinterPublicPath = PublicPath(identifier: publicMinter.path)
863 Weekday.account.storage.save(<-publicMinter, to: publicMinterStoragePath!)
864 }
865
866 access(all)
867 fun revealTraits(nftMetadataId: UInt64, traits: [{RevealableV2.RevealableTrait}]){
868 let nftMetadata = Weekday.nftMetadata[nftMetadataId]! as! Weekday.RevealableMetadata
869 nftMetadata.revealTraits(traits: traits)
870 Weekday.nftMetadata[nftMetadataId] = nftMetadata
871
872 // Event should be emitted in resource, not struct
873 var i = 1
874 while i < traits.length{
875 let traitName = traits[i].name
876 let traitValue = traits[i].value
877 emit TraitRevealed(nftUuid: nftMetadata.nftUuid, id: nftMetadata.id, trait: traitName)
878 i = i + 1
879 }
880 emit ItemRevealed(uuid: nftMetadata.nftUuid, id: nftMetadata.id, name: nftMetadata.name, description: nftMetadata.description, collection: nftMetadata.collection, editionNumber: nftMetadata.editionNumber, originalRecipient: nftMetadata.coCreator, license: nftMetadata.license, nftMetadataId: nftMetadata.id, externalURL: nftMetadata.externalURL, coCreatable: nftMetadata.coCreatable, coCreator: nftMetadata.coCreator)
881 }
882
883 init(adminAddress: Address){
884 emit AdminResourceCreated(uuid: self.uuid, adminAddress: adminAddress)
885 }
886 }
887
888 // -----------------------------------------------------------------------
889 // PublicMinter Resource
890 // -----------------------------------------------------------------------
891 // NOTE: The public minter is exposed via a capability to allow the public
892 // to mint the NFT so long as they meet the criteria.
893 // It is in the public minter that the various mint functions would be exposed
894 // such as paid mint etc.
895 // Every contract has to manage its own minting via the PublicMinter.
896 //NOTE: Customise
897 // Update the mint functions
898 access(all)
899 resource interface Minter{
900 access(all)
901 fun mintUsingAccessList(receiver: &{NonFungibleToken.CollectionPublic}, payment: @{FungibleToken.Vault}, variantId: UInt64)
902
903 access(all)
904 fun getPublicMinterDetails():{ String: AnyStruct}
905 }
906
907 access(all)
908 resource PublicMinter: TheFabricantNFTStandardV2.TFNFTPublicMinter, Minter{
909 access(all)
910 var path: String
911
912 access(all)
913 var isOpen: Bool
914
915 access(all)
916 var isAccessListOnly: Bool
917
918 access(all)
919 var isOpenAccess: Bool
920
921 // NOTE: Remove these as required and update the NFT props and
922 // resolveView to reflect this, so that views that this nft
923 // does not display are not provided
924 // Name of nft, not campaign. This will be combined with the edition number
925 access(all)
926 let name: String
927
928 access(all)
929 let description: String
930
931 access(all)
932 let collection: String
933
934 access(all)
935 let license: MetadataViews.License?
936
937 access(all)
938 let externalURL: MetadataViews.ExternalURL
939
940 access(all)
941 let coCreatable: Bool
942
943 access(all)
944 let revealableTraits:{ String: Bool}
945
946 // NOTE: The max number of mints this pM can do (eg multiple NFTs, a different minter for each one. Each NFT has a max number of mints allowed).
947 access(all)
948 var minterMintLimit: UInt64?
949
950 access(all)
951 var numberOfMints: UInt64
952
953 access(all)
954 let royalties: MetadataViews.Royalties
955
956 access(all)
957 let royaltiesTFMarketplace: TheFabricantMetadataViewsV2.Royalties
958
959 access(all)
960 var paymentAmount: UFix64
961
962 access(all)
963 let paymentType: Type
964
965 // paymentSplit: How much each address gets paid on minting of NFT
966 access(all)
967 let paymentSplit: MetadataViews.Royalties?
968
969 access(all)
970 var typeRestrictions: [Type]?
971
972 access(all)
973 var accessListId: UInt64
974
975 access(all)
976 fun changeIsOpenAccess(isOpenAccess: Bool){
977 self.isOpenAccess = isOpenAccess
978 emit PublicMinterIsOpenAccessChanged(uuid: self.uuid, name: self.name, description: self.description, collection: self.collection, path: self.path, isOpenAccess: self.isOpenAccess, isAccessListOnly: self.isAccessListOnly, isOpen: self.isOpen)
979 }
980
981 access(all)
982 fun changeIsAccessListOnly(isAccessListOnly: Bool){
983 self.isAccessListOnly = isAccessListOnly
984 emit PublicMinterIsAccessListOnly(uuid: self.uuid, name: self.name, description: self.description, collection: self.collection, path: self.path, isOpenAccess: self.isOpenAccess, isAccessListOnly: self.isAccessListOnly, isOpen: self.isOpen)
985 }
986
987 access(all)
988 fun changeMintingIsOpen(isOpen: Bool){
989 self.isOpen = isOpen
990 emit PublicMinterMintingIsOpen(uuid: self.uuid, name: self.name, description: self.description, collection: self.collection, path: self.path, isOpenAccess: self.isOpenAccess, isAccessListOnly: self.isAccessListOnly, isOpen: self.isOpen)
991 }
992
993 access(all)
994 fun setAccessListId(accessListId: UInt64){
995 self.accessListId = accessListId
996 emit PublicMinterSetAccessListId(uuid: self.uuid, name: self.name, description: self.description, collection: self.collection, path: self.path, isOpenAccess: self.isOpenAccess, isAccessListOnly: self.isAccessListOnly, isOpen: self.isOpen, accessListId: self.accessListId)
997 }
998
999 access(all)
1000 fun setPaymentAmount(amount: UFix64){
1001 self.paymentAmount = amount
1002 emit PublicMinterSetPaymentAmount(uuid: self.uuid, name: self.name, description: self.description, collection: self.collection, path: self.path, isOpenAccess: self.isOpenAccess, isAccessListOnly: self.isAccessListOnly, isOpen: self.isOpen, paymentAmount: self.paymentAmount)
1003 }
1004
1005 access(all)
1006 fun setMinterMintLimit(minterMintLimit: UInt64){
1007 self.minterMintLimit = minterMintLimit
1008 emit PublicMinterSetMinterMintLimit(uuid: self.uuid, name: self.name, description: self.description, collection: self.collection, path: self.path, isOpenAccess: self.isOpenAccess, isAccessListOnly: self.isAccessListOnly, isOpen: self.isOpen, minterMintLimit: self.minterMintLimit)
1009 }
1010
1011 // The owner of the pM can access this via borrow in tx.
1012 access(all)
1013 fun updateTypeRestrictions(types: [Type]){
1014 self.typeRestrictions = types
1015 }
1016
1017 //NOTE: Customise
1018 // mint not:
1019 // maxMint for this address has been hit √
1020 // maxSupply has been hit √
1021 // minting isn't open (!isOpen) √
1022 // payment is insufficient √
1023 // minterMintLimit is hit √
1024 // mint if:
1025 // openAccess √
1026 // OR address on access list √
1027 // Output:
1028 // NFT √
1029 // nftMetadata √
1030 // update mints per address √
1031 access(all)
1032 fun mintUsingAccessList(receiver: &{NonFungibleToken.CollectionPublic}, payment: @{FungibleToken.Vault}, variantId: UInt64){
1033 pre{
1034 self.isOpen:
1035 "Minting is not currently open!"
1036 payment.isInstance(self.paymentType):
1037 "payment vault is not requested fungible token"
1038 payment.balance == self.paymentAmount:
1039 "Incorrect payment amount provided for minting"
1040 Weekday.paymentReceiverCap != nil:
1041 "Payment Receiver Cap must be set for minting!"
1042 }
1043 post{
1044 receiver.getIDs().length == before(receiver.getIDs().length) + 1:
1045 "Minted NFT must be deposited into Collection"
1046 }
1047
1048 // Total number of mints by this pM
1049 self.numberOfMints = self.numberOfMints + 1
1050
1051 // Ensure that minterMintLimit for this pM has not been hit
1052 if self.minterMintLimit != nil{
1053 assert(self.numberOfMints <= self.minterMintLimit!, message: "Maximum number of mints for this public minter has been hit")
1054 }
1055
1056 // Ensure that the maximum supply of nfts for this contract has not been hit
1057 if Weekday.maxSupply != nil{
1058 assert(Weekday.totalSupply + 1 <= Weekday.maxSupply!, message: "Max supply for NFTs has been hit")
1059 }
1060
1061 // Ensure user hasn't minted more NFTs from this contract than allowed
1062 if Weekday.addressMintLimit != nil{
1063 if Weekday.addressMintCount[(receiver.owner!).address] != nil{
1064 assert(Weekday.addressMintCount[(receiver.owner!).address]! < Weekday.addressMintLimit!, message: "User has already minted the maximum allowance per address!")
1065 }
1066 }
1067
1068 // Check that the address has access via the access list. If isOpenAccess, then anyone can mint.
1069 if !self.isOpenAccess{
1070 assert(TheFabricantAccessList.checkAccessForAddress(accessListDetailsId: self.accessListId, address: (receiver.owner!).address), message: "User address is not on the access list and so cannot mint.")
1071 }
1072
1073 // Settle Payment
1074 if let _paymentSplit = self.paymentSplit{
1075 var i = 0
1076 let splits = _paymentSplit.getRoyalties()
1077 while i < splits.length{
1078 let split = splits[i]
1079 let receiver = split.receiver
1080 let cut = split.cut
1081 let paymentAmount = self.paymentAmount * cut
1082 if let wallet = receiver.borrow(){
1083 let pay <- payment.withdraw(amount: paymentAmount)
1084 emit MintPaymentSplitDeposited(address: (wallet.owner!).address, price: self.paymentAmount, amount: pay.balance, nftUuid: self.uuid)
1085 wallet.deposit(from: <-pay)
1086 }
1087 i = i + 1
1088 }
1089 }
1090 if payment.balance != 0.0 || payment.balance == 0.0{
1091 // pay rest to TF
1092 emit MintPaymentSplitDeposited(address: (Weekday.paymentReceiverCap!).address, price: self.paymentAmount, amount: payment.balance, nftUuid: self.uuid)
1093 }
1094 (( // Deposit has to occur outside of above if statement as resource must be moved or destroyed
1095 Weekday.paymentReceiverCap!).borrow()!).deposit(from: <-payment)
1096 let nft <- create NFT(originalRecipient: (receiver.owner!).address, license: self.license)
1097 Weekday.createNftMetadata(id: nft.id, nftUuid: nft.uuid, variantId: variantId, name: self.name, description: self.description, collection: self.collection, characteristics:{} , license: nft.license, externalURL: self.externalURL, coCreatable: self.coCreatable, coCreator: (receiver.owner!).address, editionNumber: nft.editionNumber, maxEditionNumber: nft.maxEditionNumber, revealableTraits: self.revealableTraits, royalties: self.royalties, royaltiesTFMarketplace: self.royaltiesTFMarketplace)
1098
1099 //NOTE: Event is emitted here and not in nft init because
1100 // data is split between RevealableMetadata and nft,
1101 // so not all event data is accessible during nft init
1102 emit ItemMintedAndTransferred(uuid: nft.uuid, id: nft.id, name: (Weekday.nftMetadata[nft.nftMetadataId]!).name, description: (Weekday.nftMetadata[nft.nftMetadataId]!).description, collection: (Weekday.nftMetadata[nft.nftMetadataId]!).collection, editionNumber: nft.editionNumber, originalRecipient: nft.originalRecipient, license: self.license, nftMetadataId: nft.nftMetadataId)
1103 receiver.deposit(token: <-nft)
1104
1105 // Increment the number of mints that an address has
1106 if Weekday.addressMintCount[(receiver.owner!).address] != nil{
1107 Weekday.addressMintCount[(receiver.owner!).address] = Weekday.addressMintCount[(receiver.owner!).address]! + 1
1108 } else{
1109 Weekday.addressMintCount[(receiver.owner!).address] = 1
1110 }
1111 }
1112
1113 access(all)
1114 fun getPublicMinterDetails():{ String: AnyStruct}{
1115 let ret:{ String: AnyStruct} ={}
1116 ret["name"] = self.name
1117 ret["uuid"] = self.uuid
1118 ret["path"] = self.path
1119 ret["isOpen"] = self.isOpen
1120 ret["isAccessListOnly"] = self.isAccessListOnly
1121 ret["isOpenAccess"] = self.isOpenAccess
1122 ret["description"] = self.description
1123 ret["collection"] = self.collection
1124 ret["collectionId"] = Weekday.collectionId
1125 ret["license"] = self.license
1126 ret["externalURL"] = self.externalURL
1127 ret["coCreatable"] = self.coCreatable
1128 ret["revealableTraits"] = self.revealableTraits
1129 ret["minterMintLimit"] = self.minterMintLimit
1130 ret["numberOfMints"] = self.numberOfMints
1131 ret["royalties"] = self.royalties
1132 ret["royaltiesTFMarketplace"] = self.royaltiesTFMarketplace
1133 ret["paymentAmount"] = self.paymentAmount
1134 ret["paymentType"] = self.paymentType
1135 ret["paymentSplit"] = self.paymentSplit
1136 ret["typeRestrictions"] = self.typeRestrictions
1137 ret["accessListId"] = self.accessListId
1138 return ret
1139 }
1140
1141 init(name: String, description: String, collection: String, license: MetadataViews.License?, externalURL: MetadataViews.ExternalURL, coCreatable: Bool, revealableTraits:{ String: Bool}, minterMintLimit: UInt64?, royalties: MetadataViews.Royalties, royaltiesTFMarketplace: TheFabricantMetadataViewsV2.Royalties, paymentAmount: UFix64, paymentType: Type, paymentSplit: MetadataViews.Royalties?, typeRestrictions: [Type], accessListId: UInt64){
1142
1143 // Create and save path: name_collection_uuid
1144 let pathString = "TheFabricantNFTPublicMinter_Weekday_".concat(self.uuid.toString())
1145 Weekday.publicMinterPaths[self.uuid] = pathString
1146 self.path = pathString
1147 self.isOpen = false
1148 self.isAccessListOnly = true
1149 self.isOpenAccess = false
1150 self.name = name
1151 self.description = description
1152 self.collection = collection
1153 self.license = license
1154 self.externalURL = externalURL
1155 self.coCreatable = coCreatable
1156 self.revealableTraits = revealableTraits
1157 self.minterMintLimit = minterMintLimit
1158 self.numberOfMints = 0
1159 self.royalties = royalties
1160 self.royaltiesTFMarketplace = royaltiesTFMarketplace
1161 self.paymentAmount = paymentAmount
1162 self.paymentType = paymentType
1163 self.paymentSplit = paymentSplit
1164 self.typeRestrictions = typeRestrictions
1165 self.accessListId = accessListId
1166 emit PublicMinterCreated(uuid: self.uuid, name: name, description: description, collection: collection, path: self.path)
1167 }
1168 }
1169
1170 // -----------------------------------------------------------------------
1171 // Private Utility Functions
1172 // -----------------------------------------------------------------------
1173 //NOTE: Customise
1174 // This function generates the metadata for the minted nft.
1175 access(contract)
1176 fun createNftMetadata(id: UInt64, nftUuid: UInt64, variantId: UInt64, name: String, description: String, collection: String, characteristics:{ String:{ CoCreatableV2.Characteristic}}, license: MetadataViews.License?, externalURL: MetadataViews.ExternalURL, coCreatable: Bool, coCreator: Address, editionNumber: UInt64, maxEditionNumber: UInt64?, revealableTraits:{ String: Bool}, royalties: MetadataViews.Royalties, royaltiesTFMarketplace: TheFabricantMetadataViewsV2.Royalties){
1177 pre{
1178 Weekday.baseTokenURI != nil:
1179 "Base URI must be set to mint an NFT!"
1180 variantId == 1 || variantId == 2:
1181 "Variant ID must be either 1 or 2"
1182 }
1183 var nftName: String = ""
1184 var nftDescription: String = ""
1185 var metadata:{ String: String} ={}
1186 switch variantId{
1187 case 1:
1188 nftName = "Dark Stalactite"
1189 nftDescription = "Molded in the shade, headed into the unknown. Dark stalactite is a powerful collectible eager to unfold its full AR-potential when the owner decides to. Respond to it."
1190 metadata ={ "mainImage": (Weekday.baseTokenURI!).concat("/DarkStalactite.png"), "video": (Weekday.baseTokenURI!).concat("/DarkStalactite.mp4")}
1191 case 2:
1192 nftName = "Light Stalactite"
1193 nftDescription = "Born to deflect harmful rays and betraying looks. Light stalactite will enhance the everyday life of its owner with just the right amount of AR-magic."
1194 metadata ={ "mainImage": (Weekday.baseTokenURI!).concat("/LightStalactite.png"), "video": (Weekday.baseTokenURI!).concat("/LightStalactite.mp4")}
1195 }
1196 let mD = RevealableMetadata(id: id, nftUuid: nftUuid, name: nftName, description: nftDescription, collection: collection, metadata: metadata, characteristics: characteristics, license: license, externalURL: externalURL, coCreatable: coCreatable, coCreator: coCreator, editionNumber: editionNumber, maxEditionNumber: maxEditionNumber, revealableTraits: revealableTraits, royalties: royalties, royaltiesTFMarketplace: royaltiesTFMarketplace)
1197 Weekday.nftMetadata[id] = mD
1198 }
1199
1200 access(self)
1201 fun nftsCanBeUsedForMint(receiver: &{NonFungibleToken.CollectionPublic}, refs: [&{NonFungibleToken.NFT}], typeRestrictions: [Type]): Bool{
1202 assert(typeRestrictions.length != 0, message: "There are no type restrictions for this promotion")
1203 var i = 0
1204 while i < refs.length{
1205 if typeRestrictions.contains(refs[i].getType()) && (receiver.owner!).address == (refs[i].owner!).address{
1206 return true
1207 }
1208 i = i + 1
1209 }
1210 return false
1211 }
1212
1213 // -----------------------------------------------------------------------
1214 // Public Utility Functions
1215 // -----------------------------------------------------------------------
1216 // createEmptyCollection creates an empty Collection
1217 // and returns it to the caller so that they can own NFTs
1218 access(all)
1219 fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection}{
1220 return <-create Collection()
1221 }
1222
1223 access(all)
1224 fun getPublicMinterPaths():{ UInt64: String}{
1225 return Weekday.publicMinterPaths
1226 }
1227
1228 access(all)
1229 fun getNftIdsToOwner():{ UInt64: Address}{
1230 return Weekday.nftIdsToOwner
1231 }
1232
1233 access(all)
1234 fun getMaxSupply(): UInt64?{
1235 return Weekday.maxSupply
1236 }
1237
1238 access(all)
1239 fun getTotalSupply(): UInt64{
1240 return Weekday.totalSupply
1241 }
1242
1243 access(all)
1244 fun getCollectionId(): String?{
1245 return Weekday.collectionId
1246 }
1247
1248 access(all)
1249 fun getNftMetadatas():{ UInt64:{ RevealableV2.RevealableMetadata}}{
1250 return self.nftMetadata
1251 }
1252
1253 access(all)
1254 fun getPaymentCap(): Address?{
1255 return Weekday.paymentReceiverCap?.address
1256 }
1257
1258 access(all)
1259 fun getBaseUri(): String?{
1260 return Weekday.baseTokenURI
1261 }
1262
1263 access(all)
1264 view fun getContractViews(resourceType: Type?): [Type]{
1265 return []
1266 }
1267
1268 access(all)
1269 view fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct?{
1270 return nil
1271 }
1272
1273 // -----------------------------------------------------------------------
1274 // Contract Init
1275 // -----------------------------------------------------------------------
1276 init(){
1277 self.totalSupply = 0
1278 self.maxSupply = nil
1279 self.publicMinterPaths ={}
1280 self.collectionId = nil
1281 self.nftIdsToOwner ={}
1282 self.addressMintCount ={}
1283 self.paymentReceiverCap = nil
1284 self.nftMetadata ={}
1285 self.addressMintLimit = nil
1286 self.baseTokenURI = nil
1287 self.WeekdayCollectionStoragePath = /storage/WeekdayCollectionStoragePath
1288 self.WeekdayCollectionPublicPath = /public/WeekdayCollectionPublicPath
1289 self.WeekdayProviderStoragePath = /private/WeekdayProviderStoragePath
1290 self.WeekdayAdminStoragePath = /storage/WeekdayAdminStoragePath
1291 self.WeekdayPublicMinterStoragePath = /storage/WeekdayPublicMinterStoragePath
1292 self.WeekdayPublicMinterPublicPath = /public/WeekdayPublicMinterPublicPath
1293 self.account.storage.save(<-create Admin(adminAddress: self.account.address), to: self.WeekdayAdminStoragePath)
1294 emit ContractInitialized()
1295 }
1296}
1297