Smart Contract

Piece

A.fdc436fd7db22e01.Piece

Deployed

16h ago
Feb 28, 2026, 12:39:20 AM UTC

Dependents

0 imports
1import FungibleToken from 0xf233dcee88fe0abe
2import FlowToken from 0x1654653399040a61
3import NonFungibleToken from 0x1d7e57aa55817448
4import MetadataViews from 0x1d7e57aa55817448
5import ViewResolver from 0x1d7e57aa55817448
6
7access(all) contract Piece: NonFungibleToken, ViewResolver {
8
9	// Collection Information
10	access(self) let collectionInfo: {String: AnyStruct}
11	// Contract Information
12	access(all) var totalSupply: UInt64
13    // Events
14    access(all) event ContractInitialized()
15    access(all) event Withdraw(id: UInt64, from: Address?)
16	access(all) event Deposit(id: UInt64, to: Address?)
17	access(all) event Minted(id: UInt64, serial: UInt64, recipient: Address, creatorID: UInt64)
18	access(all) event MetadataSuccess(creatorID: UInt64, description: String)
19	access(all) event MetadataError(error: String)
20	// Paths
21	access(all) let CollectionStoragePath: StoragePath
22	access(all) let CollectionPublicPath: PublicPath
23	access(all) let CollectionPrivatePath: PrivatePath
24	access(all) let AdministratorStoragePath: StoragePath
25	access(all) let MetadataStoragePath: StoragePath
26	access(all) let MetadataPublicPath: PublicPath
27
28	access(account) let nftStorage: @{Address: {UInt64: NFT}}
29
30	access(all) resource MetadataStorage: MetadataStoragePublic {
31		// List of Creator 
32		access(all) var creatorsIds: {UInt64: [NFTMetadata]}
33
34		init () {
35			self.creatorsIds = {}
36		}
37		access(account) fun creatorExist(_ creatorId: UInt64)  {
38				if self.creatorsIds[creatorId] == nil {
39					self.creatorsIds[creatorId] = []
40				}
41		}
42		access (account) fun metadataIsNew(_ creatorId: UInt64, _ description: String): Bool {
43			self.creatorExist(creatorId)
44			let metadata = self.findMetadata(creatorId, description)
45			if metadata == nil {
46				return true
47			} else {
48				return false
49			}
50		}
51		access(account) fun addMetadata(_ creatorId: UInt64,_ metadata: NFTMetadata) {
52
53			if self.creatorsIds[creatorId] == nil {
54				self.creatorsIds[creatorId] = []
55			}
56			self.creatorsIds[creatorId]?.append(metadata)!
57		}
58
59		access(account) fun updateMinted(_ creatorId: UInt64,_ description: String) {
60			let metadataRef = self.findMetadataRef(creatorId, description)!
61			metadataRef.updateMinted()
62		}
63				// Public Functions
64		access(account) fun findMetadataRef(_ creatorId: UInt64,_ description: String): &Piece.NFTMetadata? {
65			let metadatas = self.creatorsIds[creatorId]!
66			var i = metadatas.length - 1
67    		while i >= 0 {
68			    if (metadatas[i].description == description) {
69					let metadataRef: &Piece.NFTMetadata = (&self.creatorsIds[creatorId]![i] as &NFTMetadata)
70					return metadataRef
71				 }
72    			i = i - 1
73    		}
74			return nil
75		} 
76
77		// Public Functions
78		access(all) fun findMetadata(_ creatorId: UInt64,_ description: String): Piece.NFTMetadata? {
79			let metadatas = self.creatorsIds[creatorId]!
80			var i = metadatas.length - 1
81    		while i >= 0 {
82			    if (metadatas[i].description == description) {
83					return metadatas[i]
84				 }
85    			i = i - 1
86    		}
87			return nil
88		} 
89		access(all) fun getTimeRemaining(_ creatorID: UInt64,_ description: String): UFix64? {
90			let metadata = self.findMetadata(creatorID, description)!
91			let answer = (metadata.creationTime + 86400.0) - getCurrentBlock().timestamp
92			return answer
93		}
94	}
95
96    /// Defines the methods that are particular to this NFT contract collection
97    ///
98    access(all) resource interface MetadataStoragePublic {
99		access(all) fun getTimeRemaining(_ creatorID: UInt64,_ description: String): UFix64?
100		access(all) fun findMetadata(_ creatorId: UInt64,_ description: String): Piece.NFTMetadata?
101    }
102
103	access(all) struct NFTMetadata {
104		access(all) let creatorID: UInt64
105		access(all) var creatorUsername: String
106		access(all) let creatorAddress: Address
107		access(all) let description: String
108		access(all) let image: MetadataViews.HTTPFile
109		access(all) let metadataId: UInt64
110		access(all) var supply: UInt64
111		access(all) var minted: UInt64
112		access(all) let unlimited: Bool
113		access(all) var extra: {String: AnyStruct}
114		access(all) var timer: UInt64
115		access(all) let pieceCreationDate: String
116		access(all) let contentCreationDate: String
117		access(all) let creationTime: UFix64
118		access(all) let lockdownTime: UFix64
119		access(all) let embededHTML: String
120
121		access(account) fun updateMinted() {
122			self.minted = self.minted + 1
123			if(self.unlimited) {
124				self.supply = self.supply + 1
125			}
126		}
127		init(
128			_creatorID: UInt64,
129			_creatorUsername: String,
130			_creatorAddress: Address,
131			_description: String,
132			_image: MetadataViews.HTTPFile,
133			_supply: UInt64,
134			_extra: {String: AnyStruct},
135			_pieceCreationDate: String,
136			_contentCreationDate: String,
137			_currentTime: UFix64,
138			_lockdownTime: UFix64,
139			_embededHTML: String,
140			) {
141
142			self.metadataId = _creatorID
143			self.creatorID = _creatorID
144			self.creatorUsername = _creatorUsername
145			self.creatorAddress = _creatorAddress
146			self.description = _description
147			self.image = _image
148			self.extra = _extra
149			self.supply = _supply
150			self.unlimited = _supply == 0
151			self.minted = 0
152			self.timer = 0
153			self.pieceCreationDate = _pieceCreationDate
154			self.contentCreationDate = _contentCreationDate
155			self.creationTime = _currentTime
156			self.lockdownTime = _lockdownTime
157			self.embededHTML = _embededHTML
158		}
159	}
160
161    /// We choose the name NFT here, but this type can have any name now
162    /// could be changed to PieceNFT
163	access(all) resource NFT: NonFungibleToken.NFT {
164		access(all) let id: UInt64
165		// The 'metadataId' is what maps this NFT to its 'NFTMetadata'
166		access(all) let creatorID: UInt64
167		access(all) let serial: UInt64
168		access(all) let description: String
169		access(all) let originalMinter: Address
170
171		init(_creatorID: UInt64, _description: String, _recipient: Address) {
172
173			// Fetch the metadata blueprint
174			let metadatas = Piece.account.storage.borrow<&Piece.MetadataStorage>(from: Piece.MetadataStoragePath)!
175			let metadataRef = metadatas.findMetadata(_creatorID, _description)!
176			// Assign serial number to the NFT based on the number of minted NFTs
177			self.id = self.uuid
178			self.creatorID = _creatorID
179			self.serial = metadataRef.supply
180			self.description = _description
181			self.originalMinter = _recipient
182			// Update the total supply of this MetadataId by 1
183			metadatas.updateMinted(_creatorID, _description)
184			// Update Piece collection NFTs count 
185			Piece.totalSupply = Piece.totalSupply + 1
186			emit Minted(id: self.id, serial: self.serial, recipient: _recipient, creatorID: _creatorID)
187		}
188
189 		access(all) fun getMetadata(): NFTMetadata {
190			return Piece.getMetadata(self.creatorID, self.description )!
191		} 
192        /// createEmptyCollection creates an empty Collection
193        /// and returns it to the caller so that they can own NFTs
194        /// @{NonFungibleToken.Collection}
195        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
196            return <-Piece.createEmptyCollection(nftType: Type<@Piece.NFT>())
197        }
198
199		access(all) view fun getViews(): [Type] {
200			return [
201                Type<MetadataViews.Display>(),
202                Type<MetadataViews.Royalties>(),
203                Type<MetadataViews.Editions>(),
204                Type<MetadataViews.ExternalURL>(),
205                Type<MetadataViews.NFTCollectionData>(),
206                Type<MetadataViews.NFTCollectionDisplay>(),
207                Type<MetadataViews.Serial>(),
208                Type<MetadataViews.Traits>(),
209                Type<MetadataViews.EVMBridgedMetadata>()
210			]
211		}
212
213		access(all) fun resolveView(_ view: Type): AnyStruct? {
214			let metadata = self.getMetadata()
215			switch view {
216				case Type<MetadataViews.Display>():
217					return MetadataViews.Display(
218						name: metadata.creatorUsername.concat(" ").concat(metadata.contentCreationDate),
219						description: metadata.description,
220						thumbnail: metadata.image
221					)
222				case Type<MetadataViews.Traits>():
223/* 					let metaCopy = metadata.extra
224					metaCopy["Serial"] = self.serial */
225					return MetadataViews.dictToTraits(dict: {"String": 2}, excludedNames: nil)
226
227				case Type<MetadataViews.NFTView>():
228					return MetadataViews.NFTView(
229						id: self.id,
230						uuid: self.uuid,
231						display: self.resolveView(Type<MetadataViews.Display>()) as! MetadataViews.Display?,
232						externalURL: self.resolveView(Type<MetadataViews.ExternalURL>()) as! MetadataViews.ExternalURL?,
233						collectionData: self.resolveView(Type<MetadataViews.NFTCollectionData>()) as! MetadataViews.NFTCollectionData?,
234						collectionDisplay: self.resolveView(Type<MetadataViews.NFTCollectionDisplay>()) as! MetadataViews.NFTCollectionDisplay?,
235						royalties: self.resolveView(Type<MetadataViews.Royalties>()) as! MetadataViews.Royalties?,
236						traits: self.resolveView(Type<MetadataViews.Traits>()) as! MetadataViews.Traits?
237					)
238				case Type<MetadataViews.NFTCollectionData>():
239					return Piece.resolveContractView(resourceType: Type<@Piece.NFT>(), viewType: Type<MetadataViews.NFTCollectionData>())
240        		case Type<MetadataViews.ExternalURL>():
241        			return Piece.getCollectionAttribute(key: "website") as! MetadataViews.ExternalURL
242		        case Type<MetadataViews.NFTCollectionDisplay>():
243					return Piece.resolveContractView(resourceType: Type<@Piece.NFT>(), viewType: Type<MetadataViews.NFTCollectionDisplay>())
244				case Type<MetadataViews.Medias>():
245                    let metadata = 10
246					if metadata != nil {
247						return MetadataViews.Medias(
248							[
249								MetadataViews.Media(
250									file: MetadataViews.HTTPFile(
251										url: "metadata.embededHTML"
252									),
253									mediaType: "html"
254								)
255							]
256						)
257					}
258        		case Type<MetadataViews.Royalties>():
259          			return MetadataViews.Royalties([
260            			MetadataViews.Royalty(
261              				receiver: getAccount(Piece.account.address).capabilities.get<&FlowToken.Vault>(/public/flowTokenReceiver),
262              				cut: 0.10, // 10% royalty on secondary sales
263              				description: "The creator of the original content gets 10% of every secondary sale."
264            			)
265          			])
266				case Type<MetadataViews.Serial>():
267					return MetadataViews.Serial(
268						self.serial
269					)
270			}
271			return nil
272		}
273
274	}
275
276    /// Defines the methods that are particular to this NFT contract collection
277    ///
278    access(all) resource interface PieceCollectionPublic {
279        access(all) fun deposit(token: @{NonFungibleToken.NFT})
280        access(all) fun getIDs(): [UInt64]
281    //    access(all) fun borrowNFT(id: UInt64): &NonFungibleToken.NFT
282
283/*         access(all) fun borrowPiece(id: UInt64): &Piece.NFT? {
284            post {
285                (result == nil) || (result?.id == id):
286                    "Cannot borrow Piece NFT reference: the ID of the returned reference is incorrect"
287            }
288        } */
289    }
290
291	access(all) resource Collection: PieceCollectionPublic, NonFungibleToken.Collection {
292        // *** Collection Variables *** //
293		access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
294        // *** Collection Constructor *** //
295        init () {
296			self.ownedNFTs <- {}
297		}
298        // *** Collection Functions *** //
299
300        /// Returns a list of NFT types that this receiver accepts
301        access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
302            let supportedTypes: {Type: Bool} = {}
303            supportedTypes[Type<@Piece.NFT>()] = true
304            return supportedTypes
305        }
306        /// Returns whether or not the given type is accepted by the collection
307        /// A collection that can accept any type should just return true by default
308        access(all) view fun isSupportedNFTType(type: Type): Bool {
309            return type == Type<@Piece.NFT>()
310        }
311		// Withdraw removes a PieceNFT from the collection and moves it to the caller(for Trading)
312		access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
313			let token <- self.ownedNFTs.remove(key: withdrawID) 
314                ?? panic("This Collection doesn't own a PieceNFT by id: ".concat(withdrawID.toString()))
315
316			emit Withdraw(id: token.id, from: self.owner?.address)
317
318			return <-token
319		}
320		// Deposit takes a PieceNFT and adds it to the collections dictionary
321		// and adds the ID to the id array
322		access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
323			let newPiece <- token as! @NFT
324			let id: UInt64 = newPiece.id
325			// Add the new PieceNFT to the dictionary
326            let oldPiece <- self.ownedNFTs[id] <- newPiece
327            // Destroy old Piece in that slot
328            destroy oldPiece
329
330			emit Deposit(id: id, to: self.owner?.address)
331		}
332
333		// GetIDs returns an array of the IDs that are in the collection
334		access(all) view fun getIDs(): [UInt64] {
335			return self.ownedNFTs.keys
336		}
337        /// Gets the amount of NFTs stored in the collection
338        access(all) view fun getLength(): Int {
339            return self.ownedNFTs.length
340        }
341
342		// BorrowNFT gets a reference to an NFT in the collection
343		access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
344			return &self.ownedNFTs[id]
345		}
346
347		access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
348            if let nft = &self.ownedNFTs[id] as &{NonFungibleToken.NFT}? {
349                return nft as &{ViewResolver.Resolver}
350            }
351            return nil
352		}
353        /// createEmptyCollection creates an empty Collection of the same type
354        /// and returns it to the caller
355        /// @return A an empty collection of the same type
356        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
357            return <-Piece.createEmptyCollection(nftType: Type<@Piece.NFT>())
358        }
359
360        /// Gets a reference to an NFT in the collection so that 
361        /// the caller can read its metadata and call its methods
362        ///
363        /// @param id: The ID of the wanted NFT
364        /// @return A reference to the wanted NFT resource
365        ///        
366/*         access(all) fun borrowPiece(id: UInt64): &Piece.NFT? {
367            if self.ownedNFTs[id] != nil {
368                // Create an authorized reference to allow downcasting
369                let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
370                return ref as! &Piece.NFT
371            }
372
373            return nil
374        } */
375
376
377/* 		access(all) fun claim() {
378			if let storage = &Piece.nftStorage[self.owner!.address] as &{UInt64: NFT}? {
379				for id in storage.keys {
380					self.deposit(token: <- storage.remove(key: id)!)
381				}
382			}
383		} */
384	}
385
386	access(all) resource Administrator {
387		// Function to upload the Metadata to the contract.
388 		access(all) fun createNFTMetadata(
389			channel: String,
390			creatorID: UInt64,
391			creatorUsername: String, 
392			creatorAddress: Address,
393			sourceURL: String,
394			description: String,
395			pieceCreationDate: String,
396			contentCreationDate: String,
397			lockdownOption: Int,
398			supplyOption: UInt64,
399			imgUrl: String,
400			embededHTML: String) 
401            {
402			// Load the metadata from the Piece account
403			let metadatas = Piece.account.storage.borrow<&Piece.MetadataStorage>(from: Piece.MetadataStoragePath)!
404			// Check if Metadata already exist
405 			if metadatas.metadataIsNew(creatorID, description) {
406					metadatas.addMetadata(creatorID, NFTMetadata(
407							_creatorID: creatorID,
408							_creatorUsername: creatorUsername,
409							_creatorAddress: creatorAddress,
410							_description: description,
411							_image: MetadataViews.HTTPFile(
412								url: imgUrl,
413							),
414							_supply: supplyOption,
415							_extra: {
416								"Creator username": creatorUsername,
417								"Creator ID": creatorID,
418								"Channel": channel,
419								"Text content": description,
420								"Source": sourceURL,
421								"Piece creation date": pieceCreationDate,
422								"Content creation date": contentCreationDate
423								},
424							_pieceCreationDate: pieceCreationDate,
425							_contentCreationDate: contentCreationDate,
426							_currentTime: getCurrentBlock().timestamp,
427							_lockdownTime: self.getLockdownTime(lockdownOption),
428							_embededHTML: embededHTML,
429					))
430					emit MetadataSuccess(creatorID: creatorID, description: description)
431				} else {
432					emit MetadataError(error: "A Metadata for this Event already exist")
433				} 
434			// Piece.account.save(<- metadatas, to: Piece.MetadataStoragePath)
435		} 
436
437		// mintNFT mints a new NFT and deposits
438		// it in the recipients collection
439		access(all) fun mintNFT(creatorId: UInt64, description: String, recipient: Address) {
440			pre {
441				self.isMintingAvailable(creatorId, description): "Minting for this NFT has ended or reached max supply."
442			}
443
444			let nft <- create NFT(_creatorID: creatorId, _description: description, _recipient: recipient)
445
446			if let recipientCollection = getAccount(recipient)
447				.capabilities.borrow<&{NonFungibleToken.Receiver}>(Piece.CollectionPublicPath) 
448				{
449					recipientCollection.deposit(token: <- nft)
450			} else {
451				destroy nft
452/* 				if let storage = &Piece.nftStorage[recipient] as &{UInt64: NFT}? {
453					storage[nft.id] <-! nft
454				} else {
455					Piece.nftStorage[recipient] <-! {nft.id: <- nft}
456				} */
457			}
458		} 
459
460		// create a new Administrator resource
461		access(all) fun createAdmin(): @Administrator {
462			return <- create Administrator()
463		}
464		// change piece of collection info
465		access(all) fun changeField(key: String, value: AnyStruct) {
466			Piece.collectionInfo[key] = value
467		}
468
469		access(account) view fun isMintingAvailable(_ creatorId: UInt64, _ description: String): Bool {
470            return true
471		}
472
473		access(account) fun getLockdownTime(_ lockdownOption: Int): UFix64 {
474			switch lockdownOption {
475				case 0: 
476					return 21600.0
477				case 1: 
478					return 43200.0
479				case 2:
480					return 604800.0
481				case 3: 
482					return 172800.0
483				default:
484					return 0.0
485			}
486		}
487	}
488
489    /// createEmptyCollection creates an empty Collection for the specified NFT type
490    /// and returns it to the caller so that they can own NFTs
491    access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
492        return <- create Collection()
493    }
494
495	// Get information about a NFTMetadata
496	access(all) fun getMetadata(_ creatorId: UInt64,_ description: String): Piece.NFTMetadata? {
497		let storage = Piece.account.storage.borrow<&{Piece.MetadataStoragePublic}>(from: Piece.MetadataStoragePath)!
498		let metadata = storage.findMetadata(creatorId, description)
499		return metadata
500	}
501
502	access(all) fun getCollectionInfo(): {String: AnyStruct} {
503		let collectionInfo = self.collectionInfo
504		collectionInfo["totalSupply"] = self.totalSupply
505		collectionInfo["version"] = 1
506		return collectionInfo
507	}
508
509	access(all) fun getCollectionAttribute(key: String): AnyStruct {
510		return self.collectionInfo[key] ?? panic(key.concat(" is not an attribute in this collection."))
511	}
512
513    /// Function that returns all the Metadata Views implemented by a Non Fungible Token
514    ///
515    /// @return An array of Types defining the implemented views. This value will be used by
516    ///         developers to know which parameter to pass to the resolveView() method.
517    ///
518    access(all) view fun getContractViews(resourceType: Type?): [Type] {
519        return [
520            Type<MetadataViews.NFTCollectionData>(),
521            Type<MetadataViews.NFTCollectionDisplay>(),
522            Type<MetadataViews.EVMBridgedMetadata>()
523        ]
524    }
525    /// Function that resolves a metadata view for this contract.
526    ///
527    /// @param view: The Type of the desired view.
528    /// @return A structure representing the requested view.
529    ///
530    access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
531        switch viewType {
532            case Type<MetadataViews.NFTCollectionData>():
533                let collectionData = MetadataViews.NFTCollectionData(
534                    storagePath: self.CollectionStoragePath,
535                    publicPath: self.CollectionPublicPath,
536                    publicCollection: Type<&Piece.Collection>(),
537                    publicLinkedType: Type<&Piece.Collection>(),
538                    createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} {
539                        return <-Piece.createEmptyCollection(nftType: Type<@Piece.NFT>())
540                    })
541                )
542                return collectionData
543            case Type<MetadataViews.NFTCollectionDisplay>():
544                let media = Piece.getCollectionAttribute(key: "image") as! MetadataViews.Media
545                return MetadataViews.NFTCollectionDisplay(
546                    name: "Piece",
547                    description: "Sell Pieces of any Tweet in seconds.",
548                    externalURL: MetadataViews.ExternalURL("https://piece.gg/"),
549                    squareImage: media,
550                    bannerImage: media,
551                    socials: {
552                        "twitter": MetadataViews.ExternalURL("https://twitter.com/CreateAPiece")
553                    }
554                )
555            
556/*             case Type<MetadataViews.EVMBridgedMetadata>():
557                // Implementing this view gives the project control over how the bridged NFT is represented as an ERC721
558                // when bridged to EVM on Flow via the public infrastructure bridge.
559
560                // Compose the contract-level URI. In this case, the contract metadata is located on some HTTP host,
561                // but it could be IPFS, S3, a data URL containing the JSON directly, etc.
562                return MetadataViews.EVMBridgedMetadata(
563                    name: "ExampleNFT",
564                    symbol: "XMPL",
565                    uri: MetadataViews.URI(
566                        baseURI: nil, // setting baseURI as nil sets the given value as the uri field value
567                        value: "https://example-nft.onflow.org/contract-metadata.json"
568                    )
569                ) */
570            // case Type<MetadataViews.EVMBridgedMetadata>():
571            //     return MetadataViews.EVMBridgedMetadata(
572            //         name: self.name,
573            //         symbol: "XMPL",
574            //         uri: MetadataViews.URI(
575            //             baseURI: nil,
576            //             value: SerializeMetadata.serializeNFTMetadataAsURI(&self as &{NonFungibleToken.NFT})
577            //         )
578            //     )
579        }
580        return nil
581    }
582
583	init() {
584		// Collection Info
585		self.collectionInfo = {}
586		self.collectionInfo["name"] = "Piece"
587		self.collectionInfo["description"] = "Sell Pieces of any Tweet in seconds."
588		self.collectionInfo["image"] = MetadataViews.Media(
589            			file: MetadataViews.HTTPFile(
590            				url: "https://www.piece.gg/static/media/logo.48da6adac82863dd4955abe125b5c8dd.svg"
591            			),
592            			mediaType: "image/jpeg"
593          			)			
594    	self.collectionInfo["dateCreated"] = getCurrentBlock().timestamp
595    	self.collectionInfo["website"] = MetadataViews.ExternalURL("https://www.piece.gg/")
596		self.collectionInfo["socials"] = {"Twitter": MetadataViews.ExternalURL("https://frontend-react-git-testing-piece.vercel.app/")}
597		self.totalSupply = 0
598		self.nftStorage <- {}
599
600		let identifier = "Piece_Collection".concat(self.account.address.toString())
601
602		// Set the named paths
603		self.CollectionStoragePath = StoragePath(identifier: identifier)!
604		self.CollectionPublicPath = PublicPath(identifier: identifier)!
605		self.CollectionPrivatePath = PrivatePath(identifier: identifier)!
606		self.AdministratorStoragePath = StoragePath(identifier: identifier.concat("_Administrator"))!
607		self.MetadataStoragePath = StoragePath(identifier: identifier.concat("_Metadata"))!
608		self.MetadataPublicPath = PublicPath(identifier: identifier.concat("_Metadata"))!
609
610		// Create a Collection resource and save it to storage
611		let collection <- create Collection()
612		self.account.storage.save(<- collection, to: self.CollectionStoragePath)
613        // create a public capability for the collection
614	    let collectionCap = self.account.capabilities.storage.issue<&Piece.Collection>(self.CollectionStoragePath)
615		self.account.capabilities.publish(collectionCap, at: self.CollectionPublicPath)
616		// Create a Administrator resource and save it to Piece account storage
617		let administrator <- create Administrator()
618		self.account.storage.save(<- administrator, to: self.AdministratorStoragePath)
619
620		// Create a Metadata Storage resource and save it to Piece account storage
621		let metadataStorage <- create MetadataStorage()
622		self.account.storage.save(<- metadataStorage, to: self.MetadataStoragePath)
623
624		emit ContractInitialized()
625	}
626}