|
| 1 | +import FungibleToken from 0xf233dcee88fe0abe |
| 2 | +import NonFungibleToken from 0x1d7e57aa55817448 |
| 3 | + |
| 4 | +pub contract MosaicCreatorV1: NonFungibleToken { |
| 5 | + pub event ContractInitialized() |
| 6 | + pub event TileAddedToMosaic(mosaicID: UInt32, nftID: UInt64) |
| 7 | + pub event MosaicCreated(mosaicID: UInt32) |
| 8 | + pub event Withdraw(id: UInt64, from: Address?) |
| 9 | + pub event Deposit(id: UInt64, to: Address?) |
| 10 | + pub event MomentDestroyed(id: UInt64) |
| 11 | + |
| 12 | + access(self) var mosaics: @{UInt32: Mosaic} |
| 13 | + pub var mosaicNFTMapping: {UInt32: [UInt64]} |
| 14 | + pub var nextMosaicID: UInt32 |
| 15 | + pub var totalSupply: UInt64 |
| 16 | + pub var nftToDescription: {UInt64: String} |
| 17 | + pub var nftToData: {UInt64: NFTData} |
| 18 | + |
| 19 | + pub struct MosaicData { |
| 20 | + pub let mosaicID: UInt32 |
| 21 | + pub let collection: String |
| 22 | + pub let size: UInt64 |
| 23 | + pub let locked: Bool |
| 24 | + |
| 25 | + init(mosaicID: UInt32, collection: String, size: UInt64, locked: Bool) { |
| 26 | + self.mosaicID = mosaicID |
| 27 | + self.collection = collection |
| 28 | + self.size = size |
| 29 | + self.locked = locked |
| 30 | + } |
| 31 | + } |
| 32 | + |
| 33 | + pub resource Mosaic { |
| 34 | + pub let mosaicID: UInt32 |
| 35 | + pub let collection: String |
| 36 | + pub let size: UInt64 |
| 37 | + pub var locked: Bool |
| 38 | + |
| 39 | + init(collection: String, size: UInt64) { |
| 40 | + self.mosaicID = MosaicCreatorV1.nextMosaicID |
| 41 | + MosaicCreatorV1.nextMosaicID = MosaicCreatorV1.nextMosaicID + 1 |
| 42 | + self.collection = collection |
| 43 | + self.size = size |
| 44 | + self.locked = false |
| 45 | + } |
| 46 | + |
| 47 | + pub fun lock() { |
| 48 | + self.locked = true |
| 49 | + } |
| 50 | + |
| 51 | + pub fun getDetails(): {String: AnyStruct} { |
| 52 | + return { |
| 53 | + "mosaicID": self.mosaicID, |
| 54 | + "collection": self.collection, |
| 55 | + "size": self.size, |
| 56 | + "locked": self.locked, |
| 57 | + "nftIDs": MosaicCreatorV1.mosaicNFTMapping[self.mosaicID]! |
| 58 | + } |
| 59 | + } |
| 60 | + } |
| 61 | + |
| 62 | + pub struct NFTData { |
| 63 | + pub let description: String |
| 64 | + pub let ownerAddress: Address |
| 65 | + pub let collectionPath: String |
| 66 | + pub let collectionCapabilityPath: String |
| 67 | + |
| 68 | + init(description: String, ownerAddress: Address, collectionPath: String, collectionCapabilityPath: String) { |
| 69 | + self.description = description |
| 70 | + self.ownerAddress = ownerAddress |
| 71 | + self.collectionPath = collectionPath |
| 72 | + self.collectionCapabilityPath = collectionCapabilityPath |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + pub resource NFT: NonFungibleToken.INFT { |
| 77 | + pub let id: UInt64 |
| 78 | + pub var description: String |
| 79 | + pub var ownerAddress: Address |
| 80 | + pub var collectionPath: String |
| 81 | + pub var collectionCapabilityPath: String |
| 82 | + |
| 83 | + init(description: String, ownerAddress: Address, collectionPath: String, collectionCapabilityPath: String) { |
| 84 | + self.id = MosaicCreatorV1.totalSupply |
| 85 | + MosaicCreatorV1.totalSupply = MosaicCreatorV1.totalSupply + 1 |
| 86 | + self.description = description |
| 87 | + self.ownerAddress = ownerAddress |
| 88 | + self.collectionPath = collectionPath |
| 89 | + self.collectionCapabilityPath = collectionCapabilityPath |
| 90 | + MosaicCreatorV1.nftToDescription[self.id] = description |
| 91 | + MosaicCreatorV1.nftToData[self.id] = NFTData(description: description, ownerAddress: ownerAddress, collectionPath: collectionPath, collectionCapabilityPath: collectionCapabilityPath) |
| 92 | + } |
| 93 | + |
| 94 | + pub fun updateDescription(newDescription: String) { |
| 95 | + self.description = newDescription |
| 96 | + MosaicCreatorV1.nftToDescription[self.id] = newDescription |
| 97 | + let nftData = MosaicCreatorV1.nftToData[self.id]! |
| 98 | + MosaicCreatorV1.nftToData[self.id] = NFTData(description: newDescription, ownerAddress: nftData.ownerAddress, collectionPath: nftData.collectionPath, collectionCapabilityPath: nftData.collectionCapabilityPath) |
| 99 | + } |
| 100 | + |
| 101 | + pub fun updateMetadata(newOwnerAddress: Address, newCollectionPath: String, newCollectionCapabilityPath: String) { |
| 102 | + self.ownerAddress = newOwnerAddress |
| 103 | + self.collectionPath = newCollectionPath |
| 104 | + self.collectionCapabilityPath = newCollectionCapabilityPath |
| 105 | + let nftData = MosaicCreatorV1.nftToData[self.id]! |
| 106 | + MosaicCreatorV1.nftToData[self.id] = NFTData(description: nftData.description, ownerAddress: newOwnerAddress, collectionPath: newCollectionPath, collectionCapabilityPath: newCollectionCapabilityPath) |
| 107 | + } |
| 108 | + |
| 109 | + destroy() { |
| 110 | + emit MomentDestroyed(id: self.id) |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + pub resource Admin { |
| 115 | + pub fun createMosaic(collection: String, size: UInt64): UInt32 { |
| 116 | + var newMosaic <- create Mosaic(collection: collection, size: size) |
| 117 | + let newID = newMosaic.mosaicID |
| 118 | + MosaicCreatorV1.mosaics[newID] <-! newMosaic |
| 119 | + MosaicCreatorV1.mosaicNFTMapping[newID] = [] |
| 120 | + emit MosaicCreated(mosaicID: newID) |
| 121 | + return newID |
| 122 | + } |
| 123 | + |
| 124 | + pub fun addTile(mosaicID: UInt32, nftID: UInt64) { |
| 125 | + // Append the NFT ID to the mosaic's list of NFTs |
| 126 | + MosaicCreatorV1.mosaicNFTMapping[mosaicID]?.append(nftID) |
| 127 | + ?? panic("Mosaic with the specified ID does not exist") |
| 128 | + emit TileAddedToMosaic(mosaicID: mosaicID, nftID: nftID) |
| 129 | + } |
| 130 | + |
| 131 | + pub fun borrowMosaic(mosaicID: UInt32): &Mosaic { |
| 132 | + return (&MosaicCreatorV1.mosaics[mosaicID] as &Mosaic?)! |
| 133 | + } |
| 134 | + |
| 135 | + pub fun getMosaicNFTMapping(mosaicID: UInt32): [UInt64]? { |
| 136 | + return MosaicCreatorV1.mosaicNFTMapping[mosaicID] |
| 137 | + } |
| 138 | + |
| 139 | + pub fun mintNFT(description: String, recipient: &{MosaicCreatorV1.MosaicCollectionPublic}, ownerAddress: Address, collectionPath: String, collectionCapabilityPath: String) { |
| 140 | + let newNFT <- create MosaicCreatorV1.NFT(description: description, ownerAddress: ownerAddress, collectionPath: collectionPath, collectionCapabilityPath: collectionCapabilityPath) |
| 141 | + recipient.deposit(token: <-newNFT) |
| 142 | + } |
| 143 | + } |
| 144 | + |
| 145 | + pub resource interface MosaicCollectionPublic { |
| 146 | + pub fun deposit(token: @NonFungibleToken.NFT) |
| 147 | + pub fun getIDs(): [UInt64] |
| 148 | + pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT? |
| 149 | + pub fun borrowTile(id: UInt64): &MosaicCreatorV1.NFT? { |
| 150 | + // If the result isn't nil, the id of the returned reference |
| 151 | + // should be the same as the argument to the function |
| 152 | + post { |
| 153 | + (result == nil) || (result?.id == id): |
| 154 | + "Cannot borrow Mosaic reference: The ID of the returned reference is incorrect" |
| 155 | + } |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + pub resource Collection: MosaicCollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic { |
| 160 | + pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT} |
| 161 | + |
| 162 | + init() { |
| 163 | + self.ownedNFTs <- {} |
| 164 | + } |
| 165 | + |
| 166 | + pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT { |
| 167 | + let nft <- self.ownedNFTs.remove(key: withdrawID) |
| 168 | + ?? panic("Cannot withdraw: NFT does not exist in the collection") |
| 169 | + emit Withdraw(id: withdrawID, from: self.owner?.address) |
| 170 | + return <-nft |
| 171 | + } |
| 172 | + |
| 173 | + pub fun deposit(token: @NonFungibleToken.NFT) { |
| 174 | + let id = token.id |
| 175 | + let oldToken <- self.ownedNFTs[id] <- token |
| 176 | + if self.owner?.address != nil { |
| 177 | + emit Deposit(id: id, to: self.owner?.address) |
| 178 | + } |
| 179 | + destroy oldToken |
| 180 | + } |
| 181 | + |
| 182 | + pub fun getIDs(): [UInt64] { |
| 183 | + return self.ownedNFTs.keys |
| 184 | + } |
| 185 | + |
| 186 | + pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT { |
| 187 | + return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)! |
| 188 | + } |
| 189 | + |
| 190 | + pub fun borrowNFTSafe(id: UInt64): &NonFungibleToken.NFT? { |
| 191 | + if let nftRef = &self.ownedNFTs[id] as &NonFungibleToken.NFT? { |
| 192 | + return nftRef |
| 193 | + } |
| 194 | + return nil |
| 195 | + } |
| 196 | + |
| 197 | + pub fun borrowTile(id: UInt64): &MosaicCreatorV1.NFT? { |
| 198 | + if let ref = &self.ownedNFTs[id] as auth &NonFungibleToken.NFT? { |
| 199 | + return ref as! &MosaicCreatorV1.NFT |
| 200 | + } else { |
| 201 | + return nil |
| 202 | + } |
| 203 | + } |
| 204 | + |
| 205 | + pub fun destroyMoments(ids: [UInt64]) { |
| 206 | + for id in ids { |
| 207 | + let token <- self.ownedNFTs.remove(key: id) |
| 208 | + ?? panic("Cannot destroy: NFT does not exist in collection: ".concat(id.toString())) |
| 209 | + emit Withdraw(id: id, from: self.owner?.address) |
| 210 | + destroy token |
| 211 | + } |
| 212 | + } |
| 213 | + |
| 214 | + destroy() { |
| 215 | + destroy self.ownedNFTs |
| 216 | + } |
| 217 | + } |
| 218 | + |
| 219 | + pub fun createEmptyCollection(): @NonFungibleToken.Collection { |
| 220 | + return <-create MosaicCreatorV1.Collection() |
| 221 | + } |
| 222 | + |
| 223 | + pub fun borrowMosaicPublic(mosaicID: UInt32): &Mosaic? { |
| 224 | + return &self.mosaics[mosaicID] as &Mosaic? |
| 225 | + } |
| 226 | + |
| 227 | + pub fun getMosaicDetails(mosaicID: UInt32): {String: AnyStruct} { |
| 228 | + let mosaicRef = self.borrowMosaicPublic(mosaicID: mosaicID) |
| 229 | + ?? panic("Mosaic with the specified ID does not exist") |
| 230 | + |
| 231 | + return mosaicRef.getDetails() |
| 232 | + } |
| 233 | + |
| 234 | + init() { |
| 235 | + self.mosaics <- {} |
| 236 | + self.mosaicNFTMapping = {} |
| 237 | + self.nextMosaicID = 0 |
| 238 | + self.totalSupply = 0 |
| 239 | + self.nftToDescription = {} |
| 240 | + self.nftToData = {} |
| 241 | + |
| 242 | + self.account.save<@Collection>(<- create Collection(), to: /storage/MosaicCollectionV1) |
| 243 | + self.account.link<&{MosaicCollectionPublic}>(/public/MosaicCollectionV1, target: /storage/MosaicCollectionV1) |
| 244 | + self.account.save<@Admin>(<- create Admin(), to: /storage/MosaicAdminV1) |
| 245 | + |
| 246 | + emit ContractInitialized() |
| 247 | + } |
| 248 | +} |
0 commit comments