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