Smart Contract
TouchstoneMidnightMunchies
A.c4b1f4387748f389.TouchstoneMidnightMunchies
1import NonFungibleToken from 0x1d7e57aa55817448
2import MetadataViews from 0x1d7e57aa55817448
3import FungibleToken from 0xf233dcee88fe0abe
4import FlowToken from 0x1654653399040a61
5import ViewResolver from 0x1d7e57aa55817448
6
7// CREATED BY: Touchstone (https://touchstone.city/), a platform crafted by your best friends at Emerald City DAO (https://ecdao.org/).
8// STATEMENT: This contract promises to keep the 5% royalty off of primary sales and 2.5% off of secondary sales to Emerald City DAO or risk permanent suspension from participation in the DAO and its tools.
9
10// import "NonFungibleToken"
11// import "MetadataViews"
12// import "FungibleToken"
13// import "FlowToken"
14// import "ViewResolver"
15
16// import "MintVerifiers"
17// import "FUSD"
18// import "EmeraldPass"
19
20access(all) contract TouchstoneMidnightMunchies: NonFungibleToken {
21
22 // Collection Information
23 access(self) let collectionInfo: {String: AnyStruct}
24
25 // Contract Information
26 access(all) var nextEditionId: UInt64
27 access(all) var nextMetadataId: UInt64
28 access(all) var totalSupply: UInt64
29
30 // Events
31 access(all) event ContractInitialized()
32 access(all) event Withdraw(id: UInt64, from: Address?)
33 access(all) event Deposit(id: UInt64, to: Address?)
34 access(all) event TouchstonePurchase(id: UInt64, recipient: Address, metadataId: UInt64, name: String, description: String, image: MetadataViews.IPFSFile, price: UFix64)
35 access(all) event Minted(id: UInt64, recipient: Address, metadataId: UInt64)
36 access(all) event MintBatch(metadataIds: [UInt64], recipients: [Address])
37
38 // Paths
39 access(all) let CollectionStoragePath: StoragePath
40 access(all) let CollectionPublicPath: PublicPath
41 access(all) let CollectionPrivatePath: PrivatePath
42 access(all) let AdministratorStoragePath: StoragePath
43
44 // Maps metadataId of NFT to NFTMetadata
45 access(account) let metadatas: {UInt64: NFTMetadata}
46
47 // Maps the metadataId of an NFT to the primary buyer
48 access(account) let primaryBuyers: {Address: {UInt64: [UInt64]}}
49
50 access(account) let nftStorage: @{Address: {UInt64: NFT}}
51
52 access(all) struct NFTMetadata {
53 access(all) let metadataId: UInt64
54 access(all) let name: String
55 access(all) let description: String
56 // The main image of the NFT
57 access(all) let image: MetadataViews.IPFSFile
58 // An optional thumbnail that can go along with it
59 // for easier loading
60 access(all) let thumbnail: MetadataViews.IPFSFile?
61 // If price is nil, defaults to the collection price
62 access(all) let price: UFix64?
63 access(all) var extra: {String: AnyStruct}
64 access(all) let supply: UInt64
65 access(all) let purchasers: {UInt64: Address}
66
67 access(account) fun purchased(serial: UInt64, buyer: Address) {
68 self.purchasers[serial] = buyer
69 }
70
71 init(_name: String, _description: String, _image: MetadataViews.IPFSFile, _thumbnail: MetadataViews.IPFSFile?, _price: UFix64?, _extra: {String: AnyStruct}, _supply: UInt64) {
72 self.metadataId = TouchstoneMidnightMunchies.nextMetadataId
73 self.name = _name
74 self.description = _description
75 self.image = _image
76 self.thumbnail = _thumbnail
77 self.price = _price
78 self.extra = _extra
79 self.supply = _supply
80 self.purchasers = {}
81 }
82 }
83
84 access(all) resource NFT: NonFungibleToken.NFT, ViewResolver.Resolver {
85 // The 'id' is the same as the 'uuid'
86 access(all) let id: UInt64
87 // The 'metadataId' is what maps this NFT to its 'NFTMetadata'
88 access(all) let metadataId: UInt64
89 access(all) let serial: UInt64
90
91 access(all) fun getMetadata(): NFTMetadata {
92 return TouchstoneMidnightMunchies.getNFTMetadata(self.metadataId)!
93 }
94
95 access(all) view fun getViews(): [Type] {
96 return [
97 Type<MetadataViews.Display>(),
98 Type<MetadataViews.ExternalURL>(),
99 Type<MetadataViews.NFTCollectionData>(),
100 Type<MetadataViews.NFTCollectionDisplay>(),
101 Type<MetadataViews.Royalties>(),
102 Type<MetadataViews.Serial>(),
103 Type<MetadataViews.Traits>(),
104 Type<MetadataViews.NFTView>()
105 ]
106 }
107
108 access(all) fun resolveView(_ view: Type): AnyStruct? {
109 switch view {
110 case Type<MetadataViews.Display>():
111 let metadata = self.getMetadata()
112 return MetadataViews.Display(
113 name: metadata.name,
114 description: metadata.description,
115 thumbnail: metadata.thumbnail ?? metadata.image
116 )
117 case Type<MetadataViews.NFTCollectionData>():
118 return MetadataViews.NFTCollectionData(
119 storagePath: TouchstoneMidnightMunchies.CollectionStoragePath,
120 publicPath: TouchstoneMidnightMunchies.CollectionPublicPath,
121 publicCollection: Type<&Collection>(),
122 publicLinkedType: Type<&Collection>(),
123 createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} {
124 return <- TouchstoneMidnightMunchies.createEmptyCollection(nftType: Type<@TouchstoneMidnightMunchies.Collection>())
125 })
126 )
127 case Type<MetadataViews.ExternalURL>():
128 return MetadataViews.ExternalURL("https://touchstone.city/discover/".concat(self.owner!.address.toString()).concat("/TouchstoneMidnightMunchies"))
129 case Type<MetadataViews.NFTCollectionDisplay>():
130 let squareMedia = MetadataViews.Media(
131 file: TouchstoneMidnightMunchies.getCollectionAttribute(key: "image") as! MetadataViews.IPFSFile,
132 mediaType: "image"
133 )
134
135 // If a banner image exists, use it
136 // Otherwise, default to the main square image
137 var bannerMedia: MetadataViews.Media? = nil
138 if let bannerImage = TouchstoneMidnightMunchies.getOptionalCollectionAttribute(key: "bannerImage") as! MetadataViews.IPFSFile? {
139 bannerMedia = MetadataViews.Media(
140 file: bannerImage,
141 mediaType: "image"
142 )
143 }
144 return MetadataViews.NFTCollectionDisplay(
145 name: TouchstoneMidnightMunchies.getCollectionAttribute(key: "name") as! String,
146 description: TouchstoneMidnightMunchies.getCollectionAttribute(key: "description") as! String,
147 externalURL: MetadataViews.ExternalURL("https://touchstone.city/discover/".concat(self.owner!.address.toString()).concat("/TouchstoneMidnightMunchies")),
148 squareImage: squareMedia,
149 bannerImage: bannerMedia ?? squareMedia,
150 socials: TouchstoneMidnightMunchies.getCollectionAttribute(key: "socials") as! {String: MetadataViews.ExternalURL}
151 )
152 case Type<MetadataViews.Royalties>():
153 return MetadataViews.Royalties([
154 // This is for Emerald City in favor of producing Touchstone, a free platform for our users. Failure to keep this in the contract may result in permanent suspension from Emerald City.
155 MetadataViews.Royalty(
156 receiver: getAccount(0x5643fd47a29770e7).capabilities.get<&FlowToken.Vault>(/public/flowTokenReceiver),
157 cut: 0.025, // 2.5% royalty on secondary sales
158 description: "Emerald City DAO receives a 2.5% royalty from secondary sales because this collection was created using Touchstone (https://touchstone.city/), a tool for creating your own NFT collections, crafted by Emerald City DAO."
159 )
160 ])
161 case Type<MetadataViews.Serial>():
162 return MetadataViews.Serial(
163 self.serial
164 )
165 case Type<MetadataViews.Traits>():
166 return MetadataViews.dictToTraits(dict: self.getMetadata().extra, excludedNames: nil)
167 case Type<MetadataViews.NFTView>():
168 return MetadataViews.NFTView(
169 id: self.id,
170 uuid: self.uuid,
171 display: self.resolveView(Type<MetadataViews.Display>()) as! MetadataViews.Display?,
172 externalURL: self.resolveView(Type<MetadataViews.ExternalURL>()) as! MetadataViews.ExternalURL?,
173 collectionData: self.resolveView(Type<MetadataViews.NFTCollectionData>()) as! MetadataViews.NFTCollectionData?,
174 collectionDisplay: self.resolveView(Type<MetadataViews.NFTCollectionDisplay>()) as! MetadataViews.NFTCollectionDisplay?,
175 royalties: self.resolveView(Type<MetadataViews.Royalties>()) as! MetadataViews.Royalties?,
176 traits: self.resolveView(Type<MetadataViews.Traits>()) as! MetadataViews.Traits?
177 )
178 }
179 return nil
180 }
181
182 init(_metadataId: UInt64, _serial: UInt64, _recipient: Address) {
183 pre {
184 TouchstoneMidnightMunchies.metadatas[_metadataId] != nil:
185 "This NFT does not exist yet."
186 _serial < TouchstoneMidnightMunchies.getNFTMetadata(_metadataId)!.supply:
187 "This serial does not exist for this metadataId."
188 !TouchstoneMidnightMunchies.getNFTMetadata(_metadataId)!.purchasers.containsKey(_serial):
189 "This serial has already been purchased."
190 }
191 self.id = self.uuid
192 self.metadataId = _metadataId
193 self.serial = _serial
194
195 // Update the buyers list so we keep track of who is purchasing
196 // if let buyersRef: auth(Mutate) &{UInt64: [UInt64]} = &TouchstoneMidnightMunchies.primaryBuyers[_recipient] {
197 // if let metadataIdMap: &[UInt64] = buyersRef[_metadataId] {
198 // metadataIdMap.append(_serial)
199 // } else {
200 // buyersRef[_metadataId] = [_serial]
201 // }
202 // } else {
203 // TouchstoneMidnightMunchies.primaryBuyers[_recipient] = {_metadataId: [_serial]}
204 // }
205
206 // Update who bought this serial inside NFTMetadata so it cannot be purchased again.
207 let metadataRef = (&TouchstoneMidnightMunchies.metadatas[_metadataId] as &NFTMetadata?)!
208 metadataRef.purchased(serial: _serial, buyer: _recipient)
209
210 TouchstoneMidnightMunchies.totalSupply = TouchstoneMidnightMunchies.totalSupply + 1
211 emit Minted(id: self.id, recipient: _recipient, metadataId: _metadataId)
212 }
213
214 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
215 return <- TouchstoneMidnightMunchies.createEmptyCollection(nftType: Type<@TouchstoneMidnightMunchies.NFT>())
216 }
217 }
218
219 access(all) resource Collection: NonFungibleToken.Collection, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic, ViewResolver.ResolverCollection {
220 // dictionary of NFT conforming tokens
221 // NFT is a resource type with an 'UInt64' ID field
222 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
223
224 // withdraw removes an NFT from the collection and moves it to the caller
225 access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
226 let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
227
228 emit Withdraw(id: token.id, from: self.owner?.address)
229
230 return <-token
231 }
232
233 // deposit takes a NFT and adds it to the collections dictionary
234 // and adds the ID to the id array
235 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
236 let token: @TouchstoneMidnightMunchies.NFT <- token as! @TouchstoneMidnightMunchies.NFT
237
238 let id: UInt64 = token.id
239
240 // add the new token to the dictionary which removes the old one
241 let oldToken: @{NonFungibleToken.NFT}? <- self.ownedNFTs[id] <- token
242
243 emit Deposit(id: id, to: self.owner?.address)
244
245 destroy oldToken
246 }
247
248 // getIDs returns an array of the IDs that are in the collection
249 access(all) view fun getIDs(): [UInt64] {
250 return self.ownedNFTs.keys
251 }
252
253 access(all) view fun getLength(): Int {
254 return self.ownedNFTs.length
255 }
256
257 access(all) fun forEachID(_ f: fun (UInt64): Bool): Void {}
258
259 /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
260 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
261 let supportedTypes: {Type: Bool} = {}
262 supportedTypes[Type<@TouchstoneMidnightMunchies.NFT>()] = true
263 return supportedTypes
264 }
265
266 /// Returns whether or not the given type is accepted by the collection
267 /// A collection that can accept any type should just return true by default
268 access(all) view fun isSupportedNFTType(type: Type): Bool {
269 return type == Type<@TouchstoneMidnightMunchies.NFT>()
270 }
271
272 // borrowNFT gets a reference to an NFT in the collection
273 // so that the caller can read its metadata and call its methods
274 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
275 return (&self.ownedNFTs[id])
276 }
277
278 access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
279 pre {
280 self.ownedNFTs[id] != nil : "NFT not in collection"
281 }
282 let nft: &{NonFungibleToken.NFT} = (&self.ownedNFTs[id])!
283 let tokenRef = nft as! &TouchstoneMidnightMunchies.NFT
284 return tokenRef
285 }
286
287 access(all) fun claim() {
288 if let storage: auth(Mutate) &{UInt64: TouchstoneMidnightMunchies.NFT} = &TouchstoneMidnightMunchies.nftStorage[self.owner!.address] {
289 for id in storage.keys {
290 self.deposit(token: <- storage.remove(key: id)!)
291 }
292 }
293 }
294
295 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
296 return <- TouchstoneMidnightMunchies.createEmptyCollection(nftType: Type<@TouchstoneMidnightMunchies.NFT>())
297 }
298
299 init () {
300 self.ownedNFTs <- {}
301 }
302 }
303
304 // A function to mint NFTs.
305 // You can only call this function if minting
306 // is currently active.
307 access(all) fun mintNFT(metadataId: UInt64, recipient: &{NonFungibleToken.Receiver}, payment: @FlowToken.Vault, serial: UInt64): UInt64 {
308 pre {
309 self.canMint(): "Minting is currently closed by the Administrator!"
310 payment.balance == self.getPriceOfNFT(metadataId):
311 "Payment does not match the price. You passed in ".concat(payment.balance.toString()).concat(" but this NFT costs ").concat(self.getPriceOfNFT(metadataId)!.toString())
312 }
313 let price: UFix64 = self.getPriceOfNFT(metadataId)!
314
315 // Confirm recipient passes all verifiers
316 // for verifier in self.getMintVerifiers() {
317 // let params = {"minter": recipient.owner!.address}
318 // if let error = verifier.verify(params) {
319 // panic(error)
320 // }
321 // }
322
323 // Handle Emerald City DAO royalty (5%)
324 let EmeraldCityTreasury = getAccount(0x5643fd47a29770e7).capabilities.get<&FlowToken.Vault>(/public/flowTokenReceiver)
325 .borrow()!
326 let emeraldCityCut: UFix64 = 0.05 * price
327
328 // Handle royalty to user that was configured upon creation
329 if let royalty = TouchstoneMidnightMunchies.getOptionalCollectionAttribute(key: "royalty") as! MetadataViews.Royalty? {
330 royalty.receiver.borrow()!.deposit(from: <- payment.withdraw(amount: price * royalty.cut))
331 }
332
333 EmeraldCityTreasury.deposit(from: <- payment.withdraw(amount: emeraldCityCut))
334
335 // Give the rest to the collection owner
336 let paymentRecipient = self.account.capabilities.get<&FlowToken.Vault>(/public/flowTokenReceiver)
337 .borrow()!
338 paymentRecipient.deposit(from: <- payment)
339
340 // Mint the nft
341 let nft <- create NFT(_metadataId: metadataId, _serial: serial, _recipient: recipient.owner!.address)
342 let nftId: UInt64 = nft.id
343 let metadata = self.getNFTMetadata(metadataId)!
344 self.collectionInfo["profit"] = (self.getCollectionAttribute(key: "profit") as! UFix64) + price
345
346 // Emit event
347 emit TouchstonePurchase(id: nftId, recipient: recipient.owner!.address, metadataId: metadataId, name: metadata.name, description: metadata.description, image: metadata.image, price: price)
348
349 // Deposit nft
350 recipient.deposit(token: <- nft)
351
352 return nftId
353 }
354
355 access(all) resource Administrator {
356 access(all) fun createNFTMetadata(name: String, description: String, imagePath: String, thumbnailPath: String?, ipfsCID: String, price: UFix64?, extra: {String: AnyStruct}, supply: UInt64) {
357 TouchstoneMidnightMunchies.metadatas[TouchstoneMidnightMunchies.nextMetadataId] = NFTMetadata(
358 _name: name,
359 _description: description,
360 _image: MetadataViews.IPFSFile(
361 cid: ipfsCID,
362 path: imagePath
363 ),
364 _thumbnail: thumbnailPath == nil ? nil : MetadataViews.IPFSFile(cid: ipfsCID, path: thumbnailPath),
365 _price: price,
366 _extra: extra,
367 _supply: supply
368 )
369 TouchstoneMidnightMunchies.nextMetadataId = TouchstoneMidnightMunchies.nextMetadataId + 1
370 }
371
372 // mintNFT mints a new NFT and deposits
373 // it in the recipients collection
374 access(all) fun mintNFT(metadataId: UInt64, serial: UInt64, recipient: Address) {
375 pre {
376 // EmeraldPass.isActive(user: TouchstoneMidnightMunchies.account.address): "You must have an active Emerald Pass subscription to airdrop NFTs. You can purchase Emerald Pass at https://pass.ecdao.org/"
377 }
378 let nft <- create NFT(_metadataId: metadataId, _serial: serial, _recipient: recipient)
379 if let recipientCollection = getAccount(recipient).capabilities.get<&TouchstoneMidnightMunchies.Collection>(TouchstoneMidnightMunchies.CollectionPublicPath).borrow() {
380 recipientCollection.deposit(token: <- nft)
381 } else {
382 if let storage: auth(Mutate) &{UInt64: TouchstoneMidnightMunchies.NFT} = &TouchstoneMidnightMunchies.nftStorage[recipient] {
383 storage[nft.id] <-! nft
384 } else {
385 TouchstoneMidnightMunchies.nftStorage[recipient] <-! {nft.id: <- nft}
386 }
387 }
388 }
389
390 access(all) fun mintBatch(metadataIds: [UInt64], serials: [UInt64], recipients: [Address]) {
391 pre {
392 metadataIds.length == recipients.length: "You need to pass in an equal number of metadataIds and recipients."
393 }
394 var i = 0
395 while i < metadataIds.length {
396 self.mintNFT(metadataId: metadataIds[i], serial: serials[i], recipient: recipients[i])
397 i = i + 1
398 }
399
400 emit MintBatch(metadataIds: metadataIds, recipients: recipients)
401 }
402
403 // create a new Administrator resource
404 access(all) fun createAdmin(): @Administrator {
405 return <- create Administrator()
406 }
407
408 // change piece of collection info
409 access(all) fun changeField(key: String, value: AnyStruct) {
410 TouchstoneMidnightMunchies.collectionInfo[key] = value
411 }
412 }
413
414 // public function that anyone can call to create a new empty collection
415 access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
416 return <- create Collection()
417 }
418
419 // Get information about a NFTMetadata
420 access(all) view fun getNFTMetadata(_ metadataId: UInt64): NFTMetadata? {
421 return self.metadatas[metadataId]
422 }
423
424 access(all) view fun getNFTMetadatas(): {UInt64: NFTMetadata} {
425 return self.metadatas
426 }
427
428 access(all) view fun getPrimaryBuyers(): {Address: {UInt64: [UInt64]}} {
429 return self.primaryBuyers
430 }
431
432 access(all) view fun getCollectionInfo(): {String: AnyStruct} {
433 let collectionInfo = self.collectionInfo
434 collectionInfo["metadatas"] = self.metadatas
435 collectionInfo["primaryBuyers"] = self.primaryBuyers
436 collectionInfo["totalSupply"] = self.totalSupply
437 collectionInfo["nextMetadataId"] = self.nextMetadataId
438 collectionInfo["version"] = 1
439 return collectionInfo
440 }
441
442 access(all) view fun getCollectionAttribute(key: String): AnyStruct {
443 return self.collectionInfo[key] ?? panic(key.concat(" is not an attribute in this collection."))
444 }
445
446 access(all) fun getOptionalCollectionAttribute(key: String): AnyStruct? {
447 return self.collectionInfo[key]
448 }
449
450 // access(all) fun getMintVerifiers(): [{MintVerifiers.IVerifier}] {
451 // return self.getCollectionAttribute(key: "mintVerifiers") as! [{MintVerifiers.IVerifier}]
452 // }
453
454 access(all) view fun canMint(): Bool {
455 return self.getCollectionAttribute(key: "minting") as! Bool
456 }
457
458 // Returns nil if an NFT with this metadataId doesn't exist
459 access(all) view fun getPriceOfNFT(_ metadataId: UInt64): UFix64? {
460 if let metadata: TouchstoneMidnightMunchies.NFTMetadata = self.getNFTMetadata(metadataId) {
461 let defaultPrice: UFix64 = self.getCollectionAttribute(key: "price") as! UFix64
462 if self.getCollectionAttribute(key: "lotteryBuying") as! Bool {
463 return defaultPrice
464 }
465 return metadata.price ?? defaultPrice
466 }
467 // If the metadataId doesn't exist
468 return nil
469 }
470
471 // Returns an mapping of id to NFTMetadata
472 // for the NFTs a user can claim
473 access(all) fun getClaimableNFTs(user: Address): {UInt64: NFTMetadata} {
474 let answer: {UInt64: NFTMetadata} = {}
475 if let storage: auth(Mutate) &{UInt64: TouchstoneMidnightMunchies.NFT} = &TouchstoneMidnightMunchies.nftStorage[user] {
476 for id in storage.keys {
477 let nftRef = (storage[id])!
478 answer[id] = self.getNFTMetadata(nftRef.metadataId)
479 }
480 }
481 return answer
482 }
483
484 access(all) view fun getContractViews(resourceType: Type?): [Type] {
485 return [
486 Type<MetadataViews.NFTCollectionData>()
487 ]
488 }
489
490 access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
491 return nil
492 }
493
494 init(
495 _name: String,
496 _description: String,
497 _imagePath: String,
498 _bannerImagePath: String?,
499 _minting: Bool,
500 _royalty: MetadataViews.Royalty?,
501 _defaultPrice: UFix64,
502 _paymentType: String,
503 _ipfsCID: String,
504 _lotteryBuying: Bool,
505 _socials: {String: MetadataViews.ExternalURL}
506 // _mintVerifiers: [{MintVerifiers.IVerifier}]
507 ) {
508 // Collection Info
509 self.collectionInfo = {}
510 self.collectionInfo["name"] = _name
511 self.collectionInfo["description"] = _description
512 self.collectionInfo["image"] = MetadataViews.IPFSFile(
513 cid: _ipfsCID,
514 path: _imagePath
515 )
516 if let bannerImagePath = _bannerImagePath {
517 self.collectionInfo["bannerImage"] = MetadataViews.IPFSFile(
518 cid: _ipfsCID,
519 path: _bannerImagePath
520 )
521 }
522 self.collectionInfo["ipfsCID"] = _ipfsCID
523 self.collectionInfo["socials"] = _socials
524 self.collectionInfo["minting"] = _minting
525 self.collectionInfo["lotteryBuying"] = _lotteryBuying
526 if let royalty = _royalty {
527 assert(royalty.receiver.check(), message: "The passed in royalty receiver is not valid. The royalty account must set up the intended payment token.")
528 assert(royalty.cut <= 0.95, message: "The royalty cut cannot be bigger than 95% because 5% goes to Emerald City treasury for primary sales.")
529 self.collectionInfo["royalty"] = royalty
530 }
531 self.collectionInfo["price"] = _defaultPrice
532 self.collectionInfo["paymentType"] = _paymentType
533 self.collectionInfo["dateCreated"] = getCurrentBlock().timestamp
534 // self.collectionInfo["mintVerifiers"] = _mintVerifiers
535 self.collectionInfo["profit"] = 0.0
536
537 self.nextEditionId = 0
538 self.nextMetadataId = 0
539 self.totalSupply = 0
540 self.metadatas = {}
541 self.primaryBuyers = {}
542 self.nftStorage <- {}
543
544 // Set the named paths
545 // We include the user's address in the paths.
546 // This is to prevent clashing with existing
547 // Collection paths in the ecosystem.
548 self.CollectionStoragePath = /storage/TouchstoneMidnightMunchiesCollection_0xc4b1f4387748f389
549 self.CollectionPublicPath = /public/TouchstoneMidnightMunchiesCollection_0xc4b1f4387748f389
550 self.CollectionPrivatePath = /private/TouchstoneMidnightMunchiesCollection_0xc4b1f4387748f389
551 self.AdministratorStoragePath = /storage/TouchstoneMidnightMunchiesAdministrator_0xc4b1f4387748f389
552
553 // Create a Collection resource and save it to storage
554 let collection <- create Collection()
555 self.account.storage.save(<- collection, to: self.CollectionStoragePath)
556
557 // create a public capability for the collection
558 let cap = self.account.capabilities.storage.issue<&Collection>(self.CollectionStoragePath)
559 self.account.capabilities.publish(cap, at: self.CollectionPublicPath)
560
561 // Create a Administrator resource and save it to storage
562 let administrator <- create Administrator()
563 self.account.storage.save(<- administrator, to: self.AdministratorStoragePath)
564
565 emit ContractInitialized()
566 }
567}
568