Smart Contract

MintStoreItem

A.20187093790b9aef.MintStoreItem

Deployed

1w ago
Feb 15, 2026, 09:58:10 PM UTC

Dependents

3401 imports
1/*
2    Description: 
3
4    authors: Matthew Balazsi (matthew@mint.store), Joseph Djenandji (joseph@mint.store)
5    
6    This smart contract contains the core functionality for Mint Store NFTs. 
7    
8    MINT is a platform where teams can create a fully branded environment to sell NFTs and launch branded marketplaces. 
9    This will give fans a fully immersive experience as they interact with drops, buy and sell in the marketplace, and 
10    deepen their relationships with the brand.
11
12    NFTs will be minted in groups called Editions. Each item in the edition will contain identical metadata except for 
13    the editionNumber (or print number). Editions can either be open (no limit to number of items minted), or closed 
14    (only a fixed number of items can be printed).
15
16    When a new NFT needs to be minted...
17    Here is the Recipe for the Mint Julep: 
18        1 teaspoon Powdered sugar
19        2 oz. Bourbon whiskey 
20        2 teaspoons Water 
21        4 Mint leaves
22    
23    Enjoy!
24*/
25
26// import NonFungibleToken from "./NonFungibleToken.cdc"
27// import FungibleToken from "./FungibleToken.cdc"
28// import MetadataViews from "./MetadataViews.cdc"
29
30// for tests
31// import NonFungibleToken from "0xNonFungibleToken"
32// import ViewResolver from "0xViewResolver"
33// import MetadataViews from "0xMetadataViews"
34
35// for testnet
36
37// import NonFungibleToken from 0x631e88ae7f1d7c20
38// import MetadataViews from 0x631e88ae7f1d7c20
39// import ViewResolver from 0x631e88ae7f1d7c20
40
41// for mainnet
42import NonFungibleToken from 0x1d7e57aa55817448
43import MetadataViews from 0x1d7e57aa55817448
44import ViewResolver from 0x1d7e57aa55817448
45
46
47access(all) contract MintStoreItem: NonFungibleToken {
48
49    // -----------------------------------------------------------------------
50    // MintStoreItem contract Events
51    // -----------------------------------------------------------------------
52
53    // Emitted when the MintStoreItem contract is created
54    access(all) event ContractInitialized()
55
56    // Emitted when a new Edition struct is created
57    access(all) event EditionCreated(id: UInt32, name: String, printingLimit: UInt32?)
58
59    // Emitted when Edition Metadata is updated
60    access(all) event EditionMetadaUpdated(editionID: UInt32)
61
62    // Emitted when a new Merchant is created
63    access(all) event MerchantCreated(merchantID: UInt32, name: String)
64
65
66    // Emitted when a new Merchant is updated
67    access(all) event MerchantUpdated(merchantID: UInt32, name: String)
68
69
70    // Emitted when a new item was minted
71    access(all) event ItemMinted(itemID:UInt64, merchantID: UInt32, editionID: UInt32, editionNumber: UInt32)
72
73    // Item related events 
74    //
75    // Emitted when an Item is withdrawn from a Collection
76    access(all) event Withdraw(id: UInt64, from: Address?)
77    // Emitted when an Item is deposited into a Collection
78    access(all) event Deposit(id: UInt64, to: Address?)
79    // Emitted when an Item is destroyed
80    access(all) event ItemDestroyed(id: UInt64)
81
82
83    // Named paths
84    //
85    access(all) let CollectionStoragePath: StoragePath
86    access(all) let CollectionPublicPath: PublicPath
87    access(all) let AdminStoragePath: StoragePath
88
89
90    // -----------------------------------------------------------------------
91    // MintStoreItem contract-level fields.
92    // These contain actual values that are stored in the smart contract.
93    // -----------------------------------------------------------------------
94
95    // Variable size dictionary of Editions resources
96    access(self) var editions: @{UInt32: Edition}
97
98
99    // The ID that is used to create Admins. 
100    // Every Admins should have a unique identifier.
101    access(all) var nextAdminID: UInt32
102
103    
104
105    // The ID that is used to create Editions. 
106    // Every time an Edition is created, nextEditionID is assigned 
107    // to the edition and then is incremented by 1.
108    access(all) var nextEditionID: UInt32
109
110
111    // Variable size dictionary of Merchant names
112    access(self) var merchants: {UInt32: String}
113
114    // The ID that is used to create Merchants. 
115    // Every time a Merchant is created, nextMerchantID is assigned 
116    // to the merchant and then is incremented by 1.
117    access(all) var nextMerchantID: UInt32
118
119
120    // The total number of MintStoreItem NFTs that have been created
121    // Because NFTs can be destroyed, it doesn't necessarily mean that this
122    // reflects the total number of NFTs in existence, just the number that
123    // have been minted to date. Also used as global nft IDs for minting.
124    access(all) var totalSupply: UInt64
125
126
127    // -----------------------------------------------------------------------
128    // MintStoreItem contract-level Composite Type definitions
129    // -----------------------------------------------------------------------
130    // These are just *definitions* for Types that this contract
131    // and other accounts can use. These definitions do not contain
132    // actual stored values, but an instance (or object) of one of these Types
133    // can be created by this contract that contains stored values.
134    // -----------------------------------------------------------------------
135   
136
137    // EditionData is a struct definition to have all of the same fields as the Edition resource.
138    // it can be used to publicly read Edition data
139
140    access(all) struct EditionData {  
141        access(all) let editionID: UInt32  
142        access(all) let merchantID: UInt32  
143        access(all) let name: String  
144        access(all) var items: [UInt64]  
145        access(all) var metadata: {String: String}
146        access(all) var numberOfItemsMinted: UInt32
147        access(all) var printingLimit: UInt32?
148        
149        init(editionID: UInt32) {
150
151             if MintStoreItem.editions[editionID] == nil {
152                panic("the editionID was not found")
153            }
154            let editionToRead = (&MintStoreItem.editions[editionID] as &Edition?)!
155
156            self.editionID = editionID
157            self.metadata = MintStoreItem.editions[editionID]?.metadata ?? ({} as {String: String})
158            self.merchantID = editionToRead.merchantID
159            self.name = editionToRead.name
160            self.printingLimit = editionToRead.printingLimit
161            self.numberOfItemsMinted=editionToRead.numberOfItemsMinted
162            self.items =MintStoreItem.editions[editionID]?.items ?? ([] as [UInt64])
163        }
164    }
165    // Edition is a Ressource that holds metadata associated 
166    // with a specific MintStoreItem
167    //
168    // MintStore NFTs will all reference an Edition as the owner of
169    // its metadata. The Editions are publicly accessible, so anyone can
170    // read the metadata associated with a specific EditionID
171    //
172    access(all) resource Edition {
173
174        // The unique ID for the Edition
175        access(all) let editionID: UInt32
176
177        // The ID of the merchant that owns the edition
178        access(all) let merchantID: UInt32
179
180        // Stores all the metadata about the edition as a string mapping
181        // This is not the long term way NFT metadata will be stored. It's a temporary
182        // construct while we figure out a better way to do metadata.
183        //
184        access(all) let metadata: {String: String}
185
186        // Array of items that are a part of this collection.
187        // When an item is added to the collection, its ID gets appended here.
188        access(all) var items: [UInt64]
189
190        // The number of items minted in this collection.
191        // When an item is added to the collection, the numberOfItems is incremented by 1
192        // It will be used to identify the editionNumber of an item
193        // if the edition is open (printingLimit=nil), we can keep minting new items
194        // if the edition is limited (printingLimit!=nil), we can keep minting items until we reach printingLimit
195        access(all) var numberOfItemsMinted: UInt32
196
197
198        // the limit of items that can be minted. For open editions, this value should be set to nil.
199        access(all) var printingLimit: UInt32?
200
201        // the name of the edition
202        access(all) var name: String
203
204        init(merchantID: UInt32, metadata: {String: String}, name: String, printingLimit:UInt32?) {
205            pre {
206                metadata.length != 0: "Metadata cannot be empty"
207                name!=nil: "Name is undefined"
208            }
209            self.editionID = MintStoreItem.nextEditionID
210            self.merchantID = merchantID
211            self.metadata = metadata
212            self.name = name
213            self.printingLimit = printingLimit
214            self.numberOfItemsMinted=0
215            self.items = []
216
217            
218            // Increment the ID so that it isn't used again
219            MintStoreItem.nextEditionID = MintStoreItem.nextEditionID + (1 as UInt32)
220
221            emit EditionCreated(id: self.editionID, name: self.name, printingLimit: self.printingLimit)
222        }
223
224
225        // mintItem mints a new Item and returns the newly minted Item
226        // 
227        // Pre-Conditions:
228        // If the edition is limited the number of items minted in the edition must be strictly less than the printing limit
229        //
230        // Returns: The NFT that was minted
231        // 
232        access(all) fun mintItem(): @NFT {
233            pre {
234                (self.numberOfItemsMinted < (self.printingLimit ?? (4294967295 as UInt32)  )): "We have reached the printing limit for this edition"
235            }
236
237            // Gets the number of Itms that have been minted for this Edition
238            // to use as this Item's edition number
239            let numMinted = self.numberOfItemsMinted + (1 as UInt32)
240
241            // Mint the new item
242            let newItem: @NFT <- create NFT(merchantID: self.merchantID, editionID: self.editionID, editionNumber: numMinted)
243
244
245            // Add the Item to the array of items
246            self.items.append(newItem.id)                            
247
248            // Increment the count of Items
249            self.numberOfItemsMinted = numMinted 
250
251            return <-newItem
252        }
253
254        // batchMintItems mints an arbitrary quantity of Items 
255        // and returns them as a Collection
256        // Be sure there are enough 
257        //
258        // Parameters: quantity: The quantity of Items to be minted
259        //
260        // Returns: Collection object that contains all the Items that were minted
261        //
262        access(all) fun batchMintItems(quantity: UInt32): @Collection {
263           
264            pre {
265                ((self.numberOfItemsMinted+quantity)<=(self.printingLimit ?? (4294967295 as UInt32))): "We have reached the printing limit for this edition"
266            }
267
268            let newCollection <- create Collection()
269
270            var i: UInt32 = 0
271            while i < quantity {
272                newCollection.deposit(token: <-self.mintItem())
273                i = i + (1 as UInt32)
274            }
275
276            return <-newCollection
277        }
278
279        // updateMetadata updates the metadata
280        //
281        // Parameters: 
282        //
283        // updates: a dictionary of key - values that is requested to be appended
284        //
285        // suffix: If the metadata already contains an attribute with a given key, this value should still be kept 
286        // for posteriority. Therefore, the old value to be replaced will be stored in a metadata entry with key = key+suffix. 
287        // This can offer some reassurance to the NFT owner that the metadata will never disappear.
288        // 
289        // Returns: the EditionID
290        //
291        access(all) fun updateMetadata(updates: {String:String}, suffix: String): UInt32 {
292           
293
294
295            // prevalidation 
296            // if metadata[key] exists and metadata[key+suffix] exists, we have a clash.
297            for key in updates.keys {
298
299                let newKey = key.concat(suffix)
300
301                if self.metadata[key] != nil && self.metadata[newKey]!=nil {
302                    var errorMsg = "attributes "
303                    errorMsg = errorMsg.concat(key).concat(" and ").concat(newKey).concat(" are already defined")
304                    panic(errorMsg)
305                }
306                    
307
308            }
309
310            // execution
311            for key in updates.keys {
312
313                let newKey = key.concat(suffix)
314
315                if self.metadata[key] != nil {
316                    self.metadata[newKey] = self.metadata[key]    
317                }
318                self.metadata[key] = updates[key]
319                
320            }
321
322
323            emit EditionMetadaUpdated(editionID: self.editionID)
324            
325            // Return the EditionID and return it
326            return self.editionID
327        }
328
329    }
330
331    // The struct representing an NFT Item data
332    access(all) struct ItemData {
333
334
335        // The ID of the merchant 
336        access(all) let merchantID: UInt32
337
338        // The ID of the edition that the NFT comes from
339        access(all) let editionID: UInt32
340
341        // The number of the NFT within the edition
342        access(all) let editionNumber: UInt32
343
344
345
346        init(merchantID: UInt32, editionID: UInt32, editionNumber: UInt32) {
347            self.merchantID = merchantID
348            self.editionID = editionID
349            self.editionNumber = editionNumber
350        }
351
352    }
353
354    // The resource that represents the Item NFTs
355    //
356    access(all) resource NFT: NonFungibleToken.NFT {
357
358        // Global unique item ID
359        access(all) let id: UInt64
360
361        // Struct of MintStoreItem metadata
362        access(all) let data: ItemData
363
364
365        init(merchantID: UInt32, editionID: UInt32, editionNumber: UInt32) {
366            
367            pre{
368                editionID > (0 as UInt32): "editionID cannot be 0"
369                editionNumber > (0 as UInt32): "editionNumber cannot be 0"
370            }
371            // Increment the global Item IDs
372            MintStoreItem.totalSupply = MintStoreItem.totalSupply + (1 as UInt64)
373
374            self.id = MintStoreItem.totalSupply
375
376            // Set the metadata struct
377            self.data = ItemData(merchantID: merchantID, editionID: editionID, editionNumber: editionNumber)
378
379            
380            emit ItemMinted(itemID: self.id, merchantID: merchantID, editionID: editionID, editionNumber: editionNumber)
381        }
382
383        access(all) view fun getData(): ItemData {
384            return self.data
385        }
386
387                /// createEmptyCollection creates an empty Collection
388        /// and returns it to the caller so that they can own NFTs
389        /// @{NonFungibleToken.Collection}
390        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
391            return <-MintStoreItem.createEmptyCollection(nftType: Type<@MintStoreItem.NFT>())
392        }
393
394
395        access(all) view fun getViews(): [Type] {
396            return [
397                Type<MetadataViews.Display>(),
398                Type<MetadataViews.Royalties>(),
399                Type<MetadataViews.Editions>(),
400                Type<MetadataViews.ExternalURL>(),
401                Type<MetadataViews.NFTCollectionData>(),
402                Type<MetadataViews.NFTCollectionDisplay>(),
403                Type<MetadataViews.Serial>(),
404                Type<MetadataViews.Traits>()
405            ]
406        }
407
408
409        access(all) fun resolveView(_ view: Type): AnyStruct? {
410            switch view {
411                case Type<MetadataViews.Display>():
412                    let edition = EditionData(editionID: self.data.editionID);
413                    return MetadataViews.Display(
414                        name: edition.name,
415                        description: edition.metadata["description"] ?? "",
416                        thumbnail: MetadataViews.HTTPFile(
417                            url: edition.metadata["thumbnail"] ?? ""
418                        )
419                    )
420                case Type<MetadataViews.Editions>():
421                    // There is no max number of NFTs that can be minted from this contract
422                    // so the max edition field value is set to nil
423                    let edition = EditionData(editionID: self.data.editionID);
424                    let maxNumber = edition.printingLimit ?? nil
425                    var max: UInt64? = nil;
426                    if maxNumber != nil {
427                     max = UInt64(maxNumber!)
428                    }
429                      
430
431                    let editionInfo = MetadataViews.Edition(name: edition.name, number: UInt64(self.data.editionNumber), max:max)
432                    let editionList: [MetadataViews.Edition] = [editionInfo]
433                    return MetadataViews.Editions(
434                        editionList
435                    )
436                
437                case Type<MetadataViews.Royalties>():
438                
439                  // TODO: add Royalties to editionData.
440                  // For now, we have royalty address and royalty percentage in the metadata
441                  // However, we have issues converting the String to Address and to UFix64
442                  return MetadataViews.Royalties([])
443
444                case Type<MetadataViews.ExternalURL>():
445                    let edition = EditionData(editionID: self.data.editionID);
446                    let url = edition.metadata["externalUrl"] ?? "";
447                    return MetadataViews.ExternalURL(url)
448
449                case Type<MetadataViews.NFTCollectionData>():
450                    return  MetadataViews.NFTCollectionData(
451                        storagePath: MintStoreItem.CollectionStoragePath,
452                        publicPath: MintStoreItem.CollectionPublicPath,
453                        publicCollection: Type<&MintStoreItem.Collection>(),
454                        publicLinkedType: Type<&MintStoreItem.Collection>(),
455                        createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} {
456                            return <-MintStoreItem.createEmptyCollection(nftType: Type<@MintStoreItem.NFT>())
457                        })
458                    )
459                
460                case Type<MetadataViews.NFTCollectionDisplay>():
461
462                    let edition = EditionData(editionID: self.data.editionID);
463                    let merchantName = MintStoreItem.merchants[self.data.merchantID]!
464                    let thumbnail = edition.metadata["thumbnail"] ?? "";
465                    let media = MetadataViews.Media(
466                        file: MetadataViews.HTTPFile(
467                            url: thumbnail
468                        ),
469                        mediaType: "image/png"
470                    )
471                    let url = edition.metadata["externalUrl"] ?? "";
472                    let description = edition.metadata["description"] ?? "";
473
474                    
475                return MetadataViews.NFTCollectionDisplay(
476                    name: merchantName,
477                    description: description,
478                    externalURL: MetadataViews.ExternalURL(url),
479                    squareImage: media,
480                    bannerImage: media,
481                    socials: {}
482                )
483
484                case Type<MetadataViews.Traits>():
485                    // exclude mintedTime and foo to show other uses of Traits
486                    let excludedTraits = ["name", "description", "thumbnail", "externalUrl"]
487                    let edition = EditionData(editionID: self.data.editionID);
488                    let metadata = edition.metadata;
489
490                    metadata.insert(key: "editionID", edition.editionID.toString());
491                    metadata.insert(key: "merchantID", edition.merchantID.toString());
492
493                    let traitsView = MetadataViews.dictToTraits(dict: metadata, excludedNames: excludedTraits)
494                    
495                    return traitsView
496
497
498            }
499
500            return nil
501        }
502
503
504    }
505
506     access(all) view fun getContractViews(resourceType: Type?): [Type] {
507        return []
508    }
509
510     access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
511 
512        return nil
513     }
514
515    // Admin is a special authorization resource that 
516    // allows the owner to perform important functions to modify the 
517    // various aspects of the Editions and Items
518    //
519    access(all) resource Admin {
520
521        access(all) let id: UInt32
522        // createEdition creates a new Edition struct 
523        // and stores it in the Editions dictionary in the MintStore contract
524        //
525
526        init(id: UInt32) {
527            self.id = id
528        }
529
530
531        // createEdition creates a new Edition resource and stores it
532        // in the editions mapping in the MintStoreItem contract
533        //
534        // Parameters: 
535        //  merchantID: The ID of the merchant
536        //  metadata: the associated data
537        //  name: The name of the Edition
538        //  printingLimit: We can only mint this quantity of NFTs. If printingLimit is nil there is no limit (theoretically UInt32.max)
539        //
540        access(all) fun createEdition(merchantID: UInt32, metadata: {String: String}, name: String, printingLimit: UInt32?) {
541            // Create the new Edition
542            var newEdition <- create Edition(merchantID:merchantID, metadata: metadata, name: name, printingLimit:printingLimit)
543            let newID = newEdition.editionID
544
545            // Store it in the contract storage
546            MintStoreItem.editions[newID] <-! newEdition
547
548        }
549
550
551        // borrowEdition returns a reference to an edition in the MintStoreItem
552        // contract so that the admin can call methods on it
553        //
554        // Parameters: editionID: The ID of the Edition that you want to
555        // get a reference to
556        //
557        // Returns: A reference to the Edition with all of the fields
558        // and methods exposed
559        //
560        access(all) fun borrowEdition(editionID: UInt32): &Edition {
561            pre {
562                MintStoreItem.editions[editionID] != nil: "Cannot borrow Edition: it does not exist"
563            }
564            
565            // Get a reference to the Edition and return it
566            return (&MintStoreItem.editions[editionID] as &Edition?)!
567        }
568
569        // updateEditionMetadata returns a reference to an edition in the MintStoreItem
570        // contract so that the admin can call methods on it
571        //
572        // Parameters: 
573        // editionID: The ID of the Edition that you want to update
574        //
575        // updates: a dictionary of key - values that is requested to be appended
576        //
577        // suffix: If the metadata already contains an attribute with a given key, this value should still be kept 
578        // for posteriority. Therefore, the old value to be replaced will be stored in a metadata entry with key = key+suffix. 
579        // This can offer some reassurance to the NFT owner that the metadata will never disappear.
580        // 
581        // Returns: the EditionID
582        //
583        access(all) fun updateEditionMetadata(editionID: UInt32, updates: {String:String}, suffix: String): UInt32 {
584            pre {
585                MintStoreItem.editions[editionID] != nil: "Cannot borrow Edition: it does not exist"
586            }
587
588            let editionRef = &MintStoreItem.editions[editionID] as &Edition?
589            editionRef!.updateMetadata(updates: updates, suffix: suffix)
590            
591            // Return the EditionID and return it
592            return editionID
593        }
594
595
596        access(all) fun createMerchant(merchantName: String): UInt32 {
597
598            pre {
599                merchantName != nil: "Cannot create the merchant: merchantName is nil"
600            }
601            let newID = MintStoreItem.nextMerchantID
602
603
604             // Create the new Merchant
605            MintStoreItem.merchants[newID] = merchantName
606
607             // Increment the ID so that it isn't used again
608            MintStoreItem.nextMerchantID = MintStoreItem.nextMerchantID + (1 as UInt32)
609
610            emit MerchantCreated(merchantID: newID, name: merchantName)
611            return newID
612        }
613
614
615         access(all) fun updateMerchant(merchantID: UInt32, merchantName: String): UInt32 {
616
617            pre {
618                MintStoreItem.merchants[merchantID] !=nil: "Cannot upate the merchant: merchantID is not initialized"
619                merchantName != nil: "Cannot upate the merchant: merchantName is nil"
620            }
621
622             // Update the new Merchant
623            MintStoreItem.merchants[merchantID] = merchantName
624
625            emit MerchantUpdated(merchantID: merchantID, name: merchantName)
626            return merchantID
627        }
628
629
630
631        // createNewAdmin creates a new Admin resource
632        //
633        access(all) fun createNewAdmin(): @Admin {
634            
635
636            let newID = MintStoreItem.nextAdminID
637             // Increment the ID so that it isn't used again
638            MintStoreItem.nextAdminID = MintStoreItem.nextAdminID + (1 as UInt32)
639
640            return <-create Admin(id: newID)
641        }
642
643    }
644
645
646
647    // This is the interface that users can cast their MintStoreItem Collection as
648    // to allow others to deposit MintStoreItems into their Collection. It also allows for reading
649    // the IDs of MintStoreItems in the Collection.
650    access(all) resource interface MintStoreItemCollectionPublic {
651  
652        
653    }
654
655
656
657    // Collection is a resource that every user who owns NFTs 
658    // will store in their account to manage their NFTS
659    //
660    access(all) resource Collection: NonFungibleToken.Collection, MintStoreItemCollectionPublic { 
661        // Dictionary of MintStore conforming tokens
662        // NFT is a resource type with a UInt64 ID field
663        access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
664        // access(all) var ownedNFTs: @{UInt64: MintStoreItem.NFT}
665
666        init() {
667            self.ownedNFTs <- {}
668        }
669
670
671
672
673        // withdraw removes a MintStoreItem from the Collection and moves it to the caller
674        //
675        // Parameters: withdrawID: The ID of the NFT 
676        // that is to be removed from the Collection
677        //
678        // returns: @NonFungibleToken.NFT the token that was withdrawn
679       access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
680
681            // Remove the nft from the Collection
682            let token <- self.ownedNFTs.remove(key: withdrawID) 
683                ?? panic("Cannot withdraw: MintStoreItem does not exist in the collection")
684
685            emit Withdraw(id: token.id, from: self.owner?.address)
686            
687            // Return the withdrawn token
688            return <-token
689        }
690
691        // batchWithdraw withdraws multiple tokens and returns them as a Collection
692        //
693        // Parameters: ids: An array of IDs to withdraw
694        //
695        // Returns: @NonFungibleToken.Collection: A collection that contains
696        //                                        the withdrawn MintStore items
697        //
698        access(NonFungibleToken.Withdraw) fun batchWithdraw(ids: [UInt64]): @{NonFungibleToken.Collection} {
699            // Create a new empty Collection
700            var batchCollection <- create Collection()
701            
702            // Iterate through the ids and withdraw them from the Collection
703            for id in ids {
704
705                let token <-self.withdraw(withdrawID: id)
706
707                batchCollection.deposit(token: <-token)
708            }
709            
710            // Return the withdrawn tokens
711            return <-batchCollection
712        }
713
714               /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
715        access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
716            let supportedTypes: {Type: Bool} = {}
717            supportedTypes[Type<@MintStoreItem.NFT>()] = true
718            return supportedTypes
719        }
720
721        /// Returns whether or not the given type is accepted by the collection
722        /// A collection that can accept any type should just return true by default
723        access(all) view fun isSupportedNFTType(type: Type): Bool {
724            return type == Type<@MintStoreItem.NFT>()
725        }
726
727        /// Gets the amount of NFTs stored in the collection
728        access(all) view fun getLength(): Int {
729            return self.ownedNFTs.length
730        }
731
732
733        // deposit takes a MintStoreItem and adds it to the Collections dictionary
734        //
735        // Paramters: token: the NFT to be deposited in the collection
736        //
737        access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
738            
739            // Cast the deposited token as a MintStoreItem NFT to make sure
740            // it is the correct type
741            let token <- token as! @MintStoreItem.NFT
742
743            // Get the token's ID
744            let id = token.id
745
746            // Add the new token to the dictionary
747            let oldToken <- self.ownedNFTs[id] <- token
748
749            // Only emit a deposit event if the Collection 
750            // is in an account's storage
751            if self.owner?.address != nil {
752                emit Deposit(id: id, to: self.owner?.address)
753            }
754
755            // Destroy the empty old token that was "removed"
756            destroy oldToken
757        }
758
759        // batchDeposit takes a Collection object as an argument
760        // and deposits each contained NFT into this Collection
761        access(all) fun batchDeposit(tokens: @{NonFungibleToken.Collection}) {
762
763            // Get an array of the IDs to be deposited
764            let keys = tokens.getIDs()
765
766            // Iterate through the keys in the collection and deposit each one
767            for key in keys {
768                self.deposit(token: <-tokens.withdraw(withdrawID: key))
769            }
770
771            // Destroy the empty Collection
772            destroy tokens
773        }
774
775        // getIDs returns an array of the IDs that are in the Collection
776        access(all) view fun getIDs(): [UInt64] {
777            return self.ownedNFTs.keys
778        }
779
780        // borrowNFT Returns a borrowed reference to a MintStoreItem in the Collection
781        // so that the caller can read its ID
782        //
783        // Parameters: id: The ID of the NFT to get the reference for
784        //
785        // Returns: A reference to the NFT
786        //
787        // Note: This only allows the caller to read the ID of the NFT,
788        // not any MintStoreItem specific data. Please use borrowMintStoreItem to 
789        // read MintStoreItem data.
790        //
791         access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
792            return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)
793        }
794
795        // borrowMintStoreItem returns a borrowed reference to a MintStoreItem
796        // so that the caller can read data and call methods from it.
797        // They can use this to read its editionID, editionNumber,
798        // or any edition data associated with it by
799        // getting the editionID and reading those fields from
800        // the smart contract.
801        //
802        // Parameters: id: The ID of the NFT to get the reference for
803        //
804        // // Returns: A reference to the NFT
805        // access(all) fun borrowMintStoreItem(id: UInt64): &MintStoreItem.NFT? {
806        //     if self.ownedNFTs[id] != nil {
807        //         let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
808        //         return ref as! &MintStoreItem.NFT
809        //     } else {
810        //         return nil
811        //     }
812        // }
813
814/// Borrow the view resolver for the specified NFT ID
815        access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
816            if let nft = &self.ownedNFTs[id] as &{NonFungibleToken.NFT}? {
817                return nft as &{ViewResolver.Resolver}
818            }
819            return nil
820        }
821
822        /// createEmptyCollection creates an empty Collection of the same type
823        /// and returns it to the caller
824        /// @return A an empty collection of the same type
825        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
826            return <-MintStoreItem.createEmptyCollection(nftType: Type<@MintStoreItem.NFT>())
827        }
828
829
830    }
831
832
833
834    // -----------------------------------------------------------------------
835    // MintStoreItem contract-level function definitions
836    // -----------------------------------------------------------------------
837
838    // createEmptyCollection creates a new, empty Collection object so that
839    // a user can store it in their account storage.
840    // Once they have a Collection in their storage, they are able to receive
841    // MintStoreItems in transactions.
842    //
843    access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
844        return <- create MintStoreItem.Collection()
845    }
846
847    access(all) fun createEmptyMintStoreItemCollection(): @MintStoreItem.Collection {
848        return <-create MintStoreItem.Collection()
849    }
850
851
852
853    // getMerchantIDs returns an array of the merchant IDs
854    access(all) fun getMerchantIDs(): [UInt32] {
855        return self.merchants.keys
856    }
857
858    // getMerchantNames returns an array of the merchant Names
859    access(all) fun getMerchantNames(): [String] {
860        return self.merchants.values
861    }
862
863    // getMerchant returns the merchant name with a given merchantID
864    access(all) fun getMerchant(merchantID: UInt32): String? {
865        return self.merchants[merchantID]
866    }
867
868
869    // -----------------------------------------------------------------------
870    // MintStoreItem initialization function
871    // -----------------------------------------------------------------------
872    //
873    init() {
874        // Initialize contract fields
875        self.editions <- {}
876        self.nextEditionID = 1
877        self.totalSupply = 0
878        self.merchants = {}
879        self.nextMerchantID = 1
880
881
882        self.CollectionStoragePath = /storage/MintStoreItemCollection
883        self.CollectionPublicPath = /public/MintStoreItemCollection
884        self.AdminStoragePath = /storage/MintStoreItemAdmin
885
886        // Put a new Collection in storage
887        self.account.storage.save<@Collection>(<- create Collection(), to: self.CollectionStoragePath)
888
889        // Create a public capability for the Collection
890        // self.account.link<&{MintStoreItemCollectionPublic}>(self.CollectionPublicPath, target: self.CollectionStoragePath)
891        let collectionCap = self.account.capabilities.storage.issue<&MintStoreItem.Collection>(self.CollectionStoragePath)
892        self.account.capabilities.publish(collectionCap, at: self.CollectionPublicPath)
893
894        // Put the admin ressource in storage
895        self.account.storage.save<@Admin>(<- create Admin(id: 1), to: self.AdminStoragePath)
896        self.nextAdminID = 2
897
898        emit ContractInitialized()
899    }
900
901
902}
903    
904
905