Smart Contract

MosaicCreatorV1

A.dbf7a2a1821c9ffa.MosaicCreatorV1

Deployed

2h ago
Feb 28, 2026, 11:03:11 PM UTC

Dependents

0 imports
1import FungibleToken from 0xf233dcee88fe0abe
2import NonFungibleToken from 0x1d7e57aa55817448
3
4pub 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}
249