Smart Contract

Metaverse

A.256599e1b091be12.Metaverse

Deployed

2h ago
Mar 02, 2026, 01:45:48 AM UTC

Dependents

0 imports
1//SPDX-License-Identifier : CC-BY-NC-4.0
2
3import NonFungibleToken from 0x1d7e57aa55817448
4import MetadataViews from 0x1d7e57aa55817448
5import FungibleToken from 0xf233dcee88fe0abe
6import ViewResolver from 0x1d7e57aa55817448
7
8// Metaverse
9// NFT for Metaverse
10//
11access(all) contract Metaverse: NonFungibleToken {
12
13    // Events
14    //
15    access(all) event ContractInitialized()
16    access(all) event Withdraw(id: UInt64, from: Address?)
17    access(all) event Deposit(id: UInt64, to: Address?)
18    access(all) event Minted(id: UInt64, typeID: UInt64)
19    access(all) event BatchMinted(ids: [UInt64], typeID: [UInt64])
20    access(all) event NFTBurned(id: UInt64)
21    access(all) event NFTsBurned(ids: [UInt64])
22
23    // Named Paths
24    //
25    access(all) let CollectionStoragePath: StoragePath
26    access(all) let CollectionPublicPath: PublicPath
27    access(all) let MinterStoragePath: StoragePath
28
29    // totalSupply
30    // The total number of Metaverses that have been minted
31    //
32    access(all) var totalSupply: UInt64
33
34    /// Function that resolves a metadata view for this contract.
35    ///
36    /// @param view: The Type of the desired view.
37    /// @return A structure representing the requested view.
38    ///
39    access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
40        switch viewType {
41            case Type<MetadataViews.NFTCollectionData>():
42                return MetadataViews.NFTCollectionData(
43                        storagePath: Metaverse.CollectionStoragePath,
44                        publicPath: Metaverse.CollectionPublicPath,
45                        publicCollection: Type<&Metaverse.Collection>(),
46                        publicLinkedType: Type<&Metaverse.Collection>(),
47                        createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} {
48                            return <-Metaverse.createEmptyCollection(nftType: Type<@Metaverse.NFT>())
49                        })
50                )
51            case Type<MetadataViews.NFTCollectionDisplay>():
52                    let squareMedia = MetadataViews.Media(
53                        file: MetadataViews.HTTPFile(
54                           url: "https://d19wottuqbmkwr.cloudfront.net/nft/banners1.jpg"
55                        ),
56                        mediaType: "image"
57                    )
58                    let bannerMedia = MetadataViews.Media(
59                        file: MetadataViews.HTTPFile(
60                            url: "https://d19wottuqbmkwr.cloudfront.net/nft/banners2.jpg"
61                        ),
62                        mediaType: "image"
63                    )
64                return MetadataViews.NFTCollectionDisplay(
65                        name: "Ozone Metaverse",
66                        description: "Ozone is the enterprise grade platform for virtual worlds building. Simple to use - Powerful - 100% browser based.",
67                        externalURL: MetadataViews.ExternalURL("https://ozonemetaverse.io"),
68                        squareImage: squareMedia,
69                        bannerImage: bannerMedia,
70                        socials: {
71                            "twitter": MetadataViews.ExternalURL("https://twitter.com/ozonemetaverse"),
72                            "discord": MetadataViews.ExternalURL("https://discord.gg/ozonemetaverse")
73                        }
74                    )
75        }
76        return nil
77    }
78
79    /// Function that returns all the Metadata Views implemented by a Non Fungible Token
80    ///
81    /// @return An array of Types defining the implemented views. This value will be used by
82    ///         developers to know which parameter to pass to the resolveView() method.
83    ///
84    access(all) view fun getContractViews(resourceType: Type?): [Type] {
85        return [
86            Type<MetadataViews.NFTCollectionData>(),
87            Type<MetadataViews.NFTCollectionDisplay>(),
88            Type<MetadataViews.ExternalURL>()
89        ]
90    }
91
92    // NFT
93    // Metaverse as an NFT
94    //
95    access(all) resource NFT: NonFungibleToken.NFT {
96        // The token's ID
97        access(all) let id: UInt64
98        // The token's type, e.g. 3 == Hat
99        access(all) let typeID: UInt64
100        // Token's metadata as a string dictionary
101        access(self) let metadata:  {String: String}
102
103        // initializer
104        //
105        init(initID: UInt64, initTypeID: UInt64, initMetadata: {String: String}) {
106            self.id = initID
107            self.typeID = initTypeID
108            self.metadata = initMetadata
109        }
110
111        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
112            return <- Metaverse.createEmptyCollection(nftType: Type<@Metaverse.NFT>())
113        }
114
115        access(all) view fun getViews(): [Type] {
116            return [
117                Type<MetadataViews.Display>(),
118                Type<MetadataViews.ExternalURL>(),
119                Type<MetadataViews.Royalties>(),
120                Type<MetadataViews.NFTCollectionData>(),
121                Type<MetadataViews.NFTCollectionDisplay>(),
122                Type<MetadataViews.Traits>()
123            ]
124        }
125
126         access(all) fun resolveView(_ view: Type): AnyStruct? {
127            switch view {
128                case Type<MetadataViews.Display>():
129                    let name = (self.metadata["name"] as! String)
130                    let description = (self.metadata["description"] as! String)
131                    let url: String = (self.metadata["imageUrl"] as! String)
132                    
133                    return MetadataViews.Display(
134                        name: name,
135                        description: description,
136                        thumbnail: MetadataViews.HTTPFile(
137                            url: url
138                        )
139                    )
140                case Type<MetadataViews.ExternalURL>():
141                    return MetadataViews.ExternalURL("https://ozonemetaverse.io/")
142                case Type<MetadataViews.Royalties>(): 
143                    let royalties : [MetadataViews.Royalty] = []
144                    royalties.append(MetadataViews.Royalty(receiver: getAccount(Metaverse.account.address).capabilities.get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver), cut: 0.1, description: "Ozone Metaverse Secondary Sale Royalty"))
145                    return MetadataViews.Royalties(royalties)
146                case Type<MetadataViews.NFTCollectionData>():
147                    return MetadataViews.NFTCollectionData(
148                        storagePath: Metaverse.CollectionStoragePath,
149                        publicPath: Metaverse.CollectionPublicPath,
150                        publicCollection: Type<&Metaverse.Collection>(),
151                        publicLinkedType: Type<&Metaverse.Collection>(),
152                        createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} {
153                            return <-Metaverse.createEmptyCollection(nftType: Type<@Metaverse.NFT>())
154                        })
155                    )
156                case Type<MetadataViews.NFTCollectionDisplay>():
157                    let squareMedia = MetadataViews.Media(
158                        file: MetadataViews.HTTPFile(
159                           url: "https://d19wottuqbmkwr.cloudfront.net/nft/banners1.jpg"
160                        ),
161                        mediaType: "image"
162                    )
163                    let bannerMedia = MetadataViews.Media(
164                        file: MetadataViews.HTTPFile(
165                            url: "https://d19wottuqbmkwr.cloudfront.net/nft/banners2.jpg"
166                        ),
167                        mediaType: "image"
168                    )
169                    return MetadataViews.NFTCollectionDisplay(
170                        name: "Ozone Metaverse",
171                        description: "Ozone is the enterprise grade platform for virtual worlds building. Simple to use - Powerful - 100% browser based.",
172                        externalURL: MetadataViews.ExternalURL("https://ozonemetaverse.io"),
173                        squareImage: squareMedia,
174                        bannerImage: bannerMedia,
175                        socials: {
176                            "twitter": MetadataViews.ExternalURL("https://twitter.com/ozonemetaverse"),
177                            "discord": MetadataViews.ExternalURL("https://discord.gg/ozonemetaverse")
178                        }
179                    )
180                case Type<MetadataViews.Traits>():
181                    let districtNameTrait = MetadataViews.Trait(
182                        name: "District Name", 
183                        value: self.metadata["districtName"], 
184                        displayType: nil,
185                        rarity: nil
186                    )
187                    let landRarityTrait = MetadataViews.Trait(
188                        name: "Land Rarity", 
189                        value: self.metadata["landRarity"], 
190                        displayType: nil,
191                        rarity: nil
192                    )
193                    return MetadataViews.Traits([
194                        districtNameTrait,
195                        landRarityTrait
196                    ])
197            }
198
199            return nil
200        }
201
202        // get complete metadata
203        access(all) view fun getMetadata() : {String:AnyStruct} {
204            return self.metadata;
205        }
206
207        // get metadata field by key
208        access(all) view fun getMetadataField(key:String) : AnyStruct? {
209            if let value = self.metadata[key] {
210                return value
211            }
212            return nil;
213        }
214    }
215
216    // This is the interface that users can cast their Metaverse Collection as
217    // to allow others to deposit Metaverse into their Collection. It also allows for reading
218    // the details of Metaverse in the Collection.
219    access(all) resource interface MetaverseCollectionPublic: NonFungibleToken.Collection {
220        access(all) fun deposit(token: @{NonFungibleToken.NFT})
221        access(all) view fun getNFTs(): &{UInt64: {NonFungibleToken.NFT}}
222        access(all) view fun borrowMetaverse(id: UInt64): &Metaverse.NFT? {
223            // If the result isn't nil, the id of the returned reference
224            // should be the same as the argument to the function
225            post {
226                (result == nil) || (result?.id == id):
227                    "Cannot borrow Metaverse reference: The ID of the returned reference is incorrect"
228            }
229        }
230    }
231
232    // Collection
233    // A collection of Metaverse NFTs owned by an account
234    //
235    access(all) resource Collection: MetaverseCollectionPublic {
236        // dictionary of NFT conforming tokens
237        // NFT is a resource type with an `UInt64` ID field
238        //
239        access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
240
241        // withdraw
242        // Removes an NFT from the collection and moves it to the caller
243        //
244        access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
245            let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
246
247            emit Withdraw(id: token.id, from: self.owner?.address)
248
249            return <-token
250        }
251
252        /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
253        access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
254            let supportedTypes: {Type: Bool} = {}
255            supportedTypes[Type<@Metaverse.NFT>()] = true
256            return supportedTypes
257        }
258
259        /// Returns whether or not the given type is accepted by the collection
260        /// A collection that can accept any type should just return true by default
261        access(all) view fun isSupportedNFTType(type: Type): Bool {
262            return type == Type<@Metaverse.NFT>()
263        }
264    
265        // deposit
266        // Takes a NFT and adds it to the collections dictionary
267        // and adds the ID to the id array
268        //
269        access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
270            let token <- token as! @Metaverse.NFT
271
272            let id: UInt64 = token.id
273
274            // add the new token to the dictionary which removes the old one
275            let oldToken <- self.ownedNFTs[id] <- token
276
277            emit Deposit(id: id, to: self.owner?.address)
278
279            destroy oldToken
280        }
281
282        // getIDs
283        // Returns an array of the IDs that are in the collection
284        //
285        access(all) view fun getIDs(): [UInt64] {
286            return self.ownedNFTs.keys
287        }
288
289        access(all) view fun getNFTs(): &{UInt64: {NonFungibleToken.NFT}} {
290            return (&self.ownedNFTs)
291            
292        }
293
294        // borrowNFT
295        // Gets a reference to an NFT in the collection
296        // so that the caller can read its metadata and call its methods
297        //
298        access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
299            return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
300        }
301
302        // borrowMetaverse
303        // Gets a reference to an NFT in the collection as a Metaverse,
304        // exposing all of its fields (including the typeID).
305        // This is safe as there are no functions that can be called on the Metaverse.
306        //
307        access(all) view fun borrowMetaverse(id: UInt64): &Metaverse.NFT? {
308            if self.ownedNFTs[id] != nil {
309                let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
310                return ref as! &Metaverse.NFT
311            } else {
312                return nil
313            }
314        }
315
316        access(all) view fun borrowNFTSafe(id: UInt64): &NFT? {
317            post {
318                result == nil || result!.id == id: "The returned reference's ID does not match the requested ID"
319            }
320
321            return self.ownedNFTs[id] != nil 
322                ? (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)! as! &Metaverse.NFT 
323                : nil
324        }
325
326        access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}?  {
327            let nft = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
328            let metaverseNft = nft as! &Metaverse.NFT
329            return metaverseNft
330        }
331
332        // initializer
333        //
334        init () {
335            self.ownedNFTs <- {}
336        }
337
338        /// createEmptyCollection creates an empty Collection of the same type
339        /// and returns it to the caller
340        /// @return A an empty collection of the same type
341        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
342            return <-Metaverse.createEmptyCollection(nftType: Type<@Metaverse.NFT>())
343        }
344    }
345
346    // createEmptyCollection
347    // public function that anyone can call to create a new empty collection
348    //
349    access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
350        return <- create Collection()
351    }
352
353    // NFTMinter
354    // Resource that an admin or something similar would own to be
355    // able to mint new NFTs
356    //
357	access(all) resource NFTMinter {
358
359		// mintNFT
360        // Mints a new NFT with a new ID
361		// and deposit it in the recipients collection using their collection reference
362        //
363		access(all) fun mintNFT(recipient: &{NonFungibleToken.CollectionPublic}, typeID: UInt64, metadata: {String:String}) {
364            emit Minted(id: Metaverse.totalSupply, typeID: typeID)
365
366			// deposit it in the recipient's account using their reference
367			recipient.deposit(token: <-create Metaverse.NFT(initID: Metaverse.totalSupply, initTypeID: typeID, initMetadata: metadata))
368
369            Metaverse.totalSupply = Metaverse.totalSupply + 1
370		}
371
372        // bachtMintNFT
373        // Mints a batch of NFTs
374		// and deposit it in the recipients collection using their collection reference
375        //
376		access(all) fun batchMintNFT(recipient: &{NonFungibleToken.CollectionPublic}, typeID: [UInt64], metadata: {String:String}) {
377            let idsTab: [UInt64] = []
378            let quantity = UInt64(typeID.length)
379            var i: UInt64 = 0
380            while i < quantity {
381              
382                // deposit it in the recipient's account using their reference
383			    recipient.deposit(token: <-create Metaverse.NFT(initID: Metaverse.totalSupply, initTypeID: typeID[i], initMetadata: metadata))
384
385                idsTab.append(Metaverse.totalSupply)
386
387                Metaverse.totalSupply = Metaverse.totalSupply + 1
388
389                i = i + 1
390            }
391
392            emit BatchMinted(ids: idsTab, typeID: typeID)
393		}
394	}
395
396    // fetch
397    // Get a reference to a Metaverse from an account's Collection, if available.
398    // If an account does not have a Metaverse.Collection, panic.
399    // If it has a collection but does not contain the itemID, return nil.
400    // If it has a collection and that collection contains the itemID, return a reference to that.
401    //
402    access(all) view fun fetch(_ from: Address, itemID: UInt64): &Metaverse.NFT? {
403        let collection = getAccount(from)
404            .capabilities.get<&Metaverse.Collection>(Metaverse.CollectionPublicPath)
405            .borrow()
406            ?? panic("Couldn't get collection")
407        // We trust Metaverse.Collection.borowMetaverse to get the correct itemID
408        // (it checks it before returning it).
409        return collection.borrowMetaverse(id: itemID)
410    }
411
412     access(all) view fun getAllNftsFromAccount(_ from: Address): &{UInt64: {NonFungibleToken.NFT}}? {
413        let collection = getAccount(from)
414            .capabilities.get<&Metaverse.Collection>(Metaverse.CollectionPublicPath)
415            .borrow()
416            ?? panic("Couldn't get collection")
417        return collection.getNFTs()
418    }
419
420    // initializer
421    //
422	init() {
423        // Set our named paths
424        self.CollectionStoragePath = /storage/metaverseCollectionVersionTwo
425        self.CollectionPublicPath = /public/metaverseCollectionVersionTwo
426        self.MinterStoragePath = /storage/metaverseMinterVersionTwo
427
428        // Initialize the total supply
429        self.totalSupply = 0
430
431        // Create a Minter resource and save it to storage
432        let minter <- create NFTMinter()
433        self.account.storage.save(<-minter, to: self.MinterStoragePath)
434
435        // Create and link collection to this account   
436        self.account.storage.save(<-self.createEmptyCollection(nftType: Type<@Metaverse.NFT>()), to: self.CollectionStoragePath)
437        let cap = self.account.capabilities.storage.issue<&Metaverse.Collection>(self.CollectionStoragePath)
438        self.account.capabilities.publish(cap, at: self.CollectionPublicPath)
439        emit ContractInitialized()
440	}
441}
442