Smart Contract
TuneGO
A.0d9bc5af3fc0c2e3.TuneGO
1import NonFungibleToken from 0x1d7e57aa55817448
2import MetadataViews from 0x1d7e57aa55817448
3import TicalUniverse from 0xfef48806337aabf1
4import ViewResolver from 0x1d7e57aa55817448
5
6access(all) contract TuneGO: NonFungibleToken {
7
8 // -----------------------------------------------------------------------
9 // TuneGO contract Paths
10 // -----------------------------------------------------------------------
11
12 access(all) let CollectionStoragePath: StoragePath
13 access(all) let CollectionPublicPath: PublicPath
14 access(all) let AdminPublicPath: PublicPath
15 access(all) let AdminStoragePath: StoragePath
16
17 // -----------------------------------------------------------------------
18 // TuneGO contract Events
19 // -----------------------------------------------------------------------
20
21 // Emitted when the TuneGO contract is created
22 access(all) event ContractInitialized()
23
24 // Emitted when a new Item struct is created
25 access(all) event ItemCreated(id: UInt32, metadata: {String:String})
26 // Emitted when a new series has been started
27 access(all) event NewSeriesStarted(newCurrentSeries: UInt32)
28
29 // Events for Set-Related actions
30 //
31 // Emitted when a new Set is created
32 access(all) event SetCreated(setId: UInt32, series: UInt32)
33 // Emitted when a new Item is added to a Set
34 access(all) event ItemAddedToSet(setId: UInt32, itemId: UInt32)
35 // Emitted when an Item is retired from a Set and cannot be used to mint
36 access(all) event ItemRetiredFromSet(setId: UInt32, itemId: UInt32, minted: UInt32)
37 // Emitted when a Set is locked, meaning collectibles cannot be added
38 access(all) event SetLocked(setId: UInt32)
39 // Emitted when a collectible is minted from a Set
40 access(all) event CollectibleMinted(id: UInt64, itemId: UInt32, setId: UInt32, serialNumber: UInt32)
41
42 // Events for Collection-related actions
43 //
44 // Emitted when a collectible is withdrawn from a Collection
45 access(all) event Withdraw(id: UInt64, from: Address?)
46 // Emitted when a collectible is deposited into a Collection
47 access(all) event Deposit(id: UInt64, to: Address?)
48
49 // -----------------------------------------------------------------------
50 // TuneGO contract-level fields.
51 // These contain actual values that are stored in the smart contract.
52 // -----------------------------------------------------------------------
53
54 // Series that this Set belongs to.
55 // Many Sets can exist at a time, but only one series.
56 access(all) var currentSeries: UInt32
57
58 // Variable size dictionary of Item structs
59 access(self) var itemDatas: {UInt32: Item}
60
61 // Variable size dictionary of SetData structs
62 access(self) var setDatas: {UInt32: SetData}
63
64 // Variable size dictionary of Set resources
65 access(self) var sets: @{UInt32: Set}
66
67 // The Id that is used to create Items.
68 // Every time an Item is created, nextItemId is assigned
69 // to the new Item's Id and then is incremented by one.
70 access(all) var nextItemId: UInt32
71
72 // The Id that is used to create Sets.
73 // Every time a Set is created, nextSetId is assigned
74 // to the new Set's Id and then is incremented by one.
75 access(all) var nextSetId: UInt32
76
77 // The total number of Collectible NFTs that have been created
78 // Because NFTs can be destroyed, it doesn't necessarily mean that this
79 // reflects the total number of NFTs in existence, just the number that
80 // have been minted to date.
81 access(all) var totalSupply: UInt64
82
83 // -----------------------------------------------------------------------
84 // TuneGO contract-level Composite Type definitions
85 // -----------------------------------------------------------------------
86 // These are just *definitions* for Types that this contract
87 // and other accounts can use. These definitions do not contain
88 // actual stored values, but an instance (or object) of one of these Types
89 // can be created by this contract that contains stored values.
90 // -----------------------------------------------------------------------
91
92 // Item is a Struct that holds metadata associated with a specific collectible item.
93 access(all) struct Item {
94
95 // The unique Id for the Item
96 access(all) let itemId: UInt32
97
98 // Stores all the metadata about the item as a string mapping.
99 access(all) let metadata: {String: String}
100
101 init(metadata: {String: String}) {
102 pre {
103 metadata.length != 0: "New Item metadata cannot be empty"
104 }
105 self.itemId = TuneGO.nextItemId
106 self.metadata = metadata
107
108 // Increment the Id so that it isn't used again
109 TuneGO.nextItemId = TuneGO.nextItemId + UInt32(1)
110
111 emit ItemCreated(id: self.itemId, metadata: metadata)
112 }
113 }
114
115 // A Set is a grouping of Items that make up a related group of collectibles,
116 // like sets of baseball cards.
117 // An Item can exist in multiple different sets.
118 //
119 // SetData is a struct that is stored in a field of the contract.
120 // Anyone can query the constant information
121 // about a set by calling various getters located
122 // at the end of the contract. Only the admin has the ability
123 // to modify any data in the private Set resource.
124 access(all) struct SetData {
125
126 // Unique Id for the Set
127 access(all) let setId: UInt32
128
129 // Name of the Set
130 access(all) let name: String
131
132 // Description of the Set
133 access(all) let description: String?
134
135 // Series that this Set belongs to
136 access(all) let series: UInt32
137
138 init(name: String, description: String?) {
139 pre {
140 name.length > 0: "New Set name cannot be empty"
141 }
142 self.setId = TuneGO.nextSetId
143 self.name = name
144 self.description = description
145 self.series = TuneGO.currentSeries
146
147 // Increment the setId so that it isn't used again
148 TuneGO.nextSetId = TuneGO.nextSetId + UInt32(1)
149
150 emit SetCreated(setId: self.setId, series: self.series)
151 }
152 }
153
154 // Set is a resource type that contains the functions to add and remove
155 // Items from a set and mint Collectibles.
156 //
157 // It is stored in a private field in the contract so that
158 // the admin resource can call its methods.
159 //
160 // The admin can add Items to a Set so that the set can mint Collectibles.
161 // The Collectible that is minted by a Set will be listed as belonging to
162 // the Set that minted it, as well as the Item it reference.
163 //
164 // Admin can also retire Items from the Set, meaning that the retired
165 // Item can no longer have Collectibles minted from it.
166 //
167 // If the admin locks the Set, no more Items can be added to it, but
168 // Collectibles can still be minted.
169 //
170 // If retireAll() and lock() are called back-to-back,
171 // the Set is closed off forever and nothing more can be done with it.
172 access(all) resource Set {
173
174 // Unique Id for the set
175 access(all) let setId: UInt32
176
177 // Array of items that are a part of this set.
178 // When an item is added to the set, its Id gets appended here.
179 // The Id does not get removed from this array when an Item is retired.
180 access(all) var items: [UInt32]
181
182 // Map of Item Ids that indicates if an Item in this Set can be minted.
183 // When an Item is added to a Set, it is mapped to false (not retired).
184 // When an Item is retired, this is set to true and cannot be changed.
185 access(all) var retired: {UInt32: Bool}
186
187 // Indicates if the Set is currently locked.
188 // When a Set is created, it is unlocked and Items are allowed to be added to it.
189 // When a set is locked, Items cannot be added to it.
190 // A Set can't transition from locked to unlocked. Locking is final.
191 // If a Set is locked, Items cannot be added, but Collectibles can still be minted
192 // from Items that exist in the Set.
193 access(all) var locked: Bool
194
195 // Mapping of Item Ids that indicates the number of Collectibles
196 // that have been minted for specific Items in this Set.
197 // When a Collectible is minted, this value is stored in the Collectible to
198 // show its place in the Set, eg. 42 of 100.
199 access(all) var numberMintedPerItem: {UInt32: UInt32}
200
201 init(name: String, description: String?) {
202 self.setId = TuneGO.nextSetId
203 self.items = []
204 self.retired = {}
205 self.locked = false
206 self.numberMintedPerItem = {}
207
208 // Create a new SetData for this Set and store it in contract storage
209 TuneGO.setDatas[self.setId] = SetData(name: name, description: description)
210 }
211
212 // Add an Item to the Set
213 //
214 // Pre-Conditions:
215 // The Item exists.
216 // The Set is unlocked.
217 // The Item is not present in the Set.
218 access(all) fun addItem(itemId: UInt32) {
219 pre {
220 TuneGO.itemDatas[itemId] != nil: "Cannot add the Item to Set: Item doesn't exist."
221 !self.locked: "Cannot add the Item to the Set after the set has been locked."
222 self.numberMintedPerItem[itemId] == nil: "The Item has already beed added to the set."
223 }
224
225 // Add the Item to the array of Items
226 self.items.append(itemId)
227
228 // Allow minting for Item
229 self.retired[itemId] = false
230
231 // Initialize the Collectible count to zero
232 self.numberMintedPerItem[itemId] = 0
233
234 emit ItemAddedToSet(setId: self.setId, itemId: itemId)
235 }
236
237 // Adds multiple Items to the Set
238 access(all) fun addItems(itemIds: [UInt32]) {
239 for id in itemIds {
240 self.addItem(itemId: id)
241 }
242 }
243
244 // Retire an Item from the Set. The Set can't mint new Collectibles for the Item.
245 // Pre-Conditions:
246 // The Item is part of the Set and not retired.
247 access(all) fun retireItem(itemId: UInt32) {
248 pre {
249 self.retired[itemId] != nil: "Cannot retire the Item: Item doesn't exist in this set!"
250 }
251
252 if !self.retired[itemId]! {
253 self.retired[itemId] = true
254
255 emit ItemRetiredFromSet(setId: self.setId, itemId: itemId, minted: self.numberMintedPerItem[itemId]!)
256 }
257 }
258
259 // Retire all the Items in the Set
260 access(all) fun retireAll() {
261 for id in self.items {
262 self.retireItem(itemId: id)
263 }
264 }
265
266 // Lock the Set so that no more Items can be added to it.
267 //
268 // Pre-Conditions:
269 // The Set is unlocked
270 access(all) fun lock() {
271 if !self.locked {
272 self.locked = true
273 emit SetLocked(setId: self.setId)
274 }
275 }
276
277 // Mint a new Collectible and returns the newly minted Collectible.
278 // Pre-Conditions:
279 // The Item must exist in the Set and be allowed to mint new Collectibles
280 access(all) fun mintCollectible(itemId: UInt32): @NFT {
281 pre {
282 self.retired[itemId] != nil: "Cannot mint the collectible: This item doesn't exist."
283 !self.retired[itemId]!: "Cannot mint the collectible from this item: This item has been retired."
284 }
285
286 // Gets the number of Collectibles that have been minted for this Item
287 // to use as this Collectibles's serial number
288 let minted = self.numberMintedPerItem[itemId]!
289
290 // Mint the new collectible
291 let newCollectible: @NFT <- create NFT(serialNumber: minted + UInt32(1),
292 itemId: itemId,
293 setId: self.setId)
294
295 // Increment the count of Collectibles minted for this Item
296 self.numberMintedPerItem[itemId] = minted + UInt32(1)
297
298 return <-newCollectible
299 }
300
301 // Mint an arbitrary quantity of Collectibles and return them as a Collection
302 access(all) fun batchMintCollectible(itemId: UInt32, quantity: UInt64): @Collection {
303 let newCollection <- create Collection()
304
305 var i: UInt64 = 0
306 while i < quantity {
307 newCollection.deposit(token: <-self.mintCollectible(itemId: itemId))
308 i = i + UInt64(1)
309 }
310
311 return <-newCollection
312 }
313 }
314
315 // Struct of Collectible metadata
316 access(all) struct CollectibleData {
317
318 // The Id of the Set that the Collectible comes from
319 access(all) let setId: UInt32
320
321 // The Id of the Item that the Collectible references
322 access(all) let itemId: UInt32
323
324 // The place in the edition that this Collectible was minted
325 access(all) let serialNumber: UInt32
326
327 init(setId: UInt32, itemId: UInt32, serialNumber: UInt32) {
328 self.setId = setId
329 self.itemId = itemId
330 self.serialNumber = serialNumber
331 }
332
333 }
334
335 // The resource that represents the Collectible NFT
336 access(all) resource NFT: NonFungibleToken.NFT, ViewResolver.Resolver {
337
338 access(all) event ResourceDestroyed(id: UInt64 = self.id)
339
340 // Global unique Collectible Id
341 access(all) let id: UInt64
342
343 // Struct of Collectible metadata
344 access(all) let data: CollectibleData
345
346 init(serialNumber: UInt32, itemId: UInt32, setId: UInt32) {
347
348 // Increment the global Collectible Id
349 TuneGO.totalSupply = TuneGO.totalSupply + UInt64(1)
350
351 self.id = TuneGO.totalSupply
352
353 self.data = CollectibleData(setId: setId, itemId: itemId, serialNumber: serialNumber)
354
355 emit CollectibleMinted(id: self.id, itemId: itemId, setId: setId, serialNumber: self.data.serialNumber)
356 }
357
358
359 access(all) view fun getViews(): [Type] {
360 return [
361 Type<MetadataViews.Royalties>(),
362 Type<MetadataViews.Display>(),
363 Type<MetadataViews.Editions>(),
364 Type<MetadataViews.ExternalURL>(),
365 Type<MetadataViews.NFTCollectionData>(),
366 Type<MetadataViews.NFTCollectionDisplay>(),
367 Type<MetadataViews.Serial>(),
368 Type<MetadataViews.Traits>()
369 ]
370 }
371
372 access(all) fun resolveView(_ view: Type): AnyStruct? {
373 switch view {
374 case Type<MetadataViews.Royalties>():
375 return MetadataViews.Royalties(
376 []
377 )
378 case Type<MetadataViews.Display>():
379 let metadata = TuneGO.getItemMetadata(itemId: self.data.itemId)!
380 let assetUrl = metadata["Media URL"]!
381 return MetadataViews.Display(
382 name: metadata["Title"]!,
383 description: metadata["Description"]!,
384 thumbnail: MetadataViews.HTTPFile(
385 url: assetUrl.slice(from: 0, upTo: assetUrl.length - 3).concat("gif")
386 )
387 )
388 case Type<MetadataViews.Editions>():
389 let editionInfo = MetadataViews.Edition(name: self.id == 1 ? "Tical Universe" : "TuneKitties", number: self.id, max: nil)
390 let editionList: [MetadataViews.Edition] = [editionInfo]
391 return MetadataViews.Editions(
392 editionList
393 )
394 case Type<MetadataViews.Serial>():
395 return MetadataViews.Serial(
396 self.uuid
397 )
398 case Type<MetadataViews.ExternalURL>():
399 return MetadataViews.ExternalURL("https://www.tunegonft.com/collectible/".concat(self.uuid.toString()))
400 case Type<MetadataViews.NFTCollectionData>():
401 return TuneGO.resolveContractView(resourceType: Type<@TuneGO.NFT>(), viewType: Type<MetadataViews.NFTCollectionData>())
402 case Type<MetadataViews.NFTCollectionDisplay>():
403 return TuneGO.resolveContractView(resourceType: Type<@TuneGO.NFT>(), viewType: Type<MetadataViews.NFTCollectionDisplay>())
404 case Type<MetadataViews.Traits>():
405 let metadata = TuneGO.getItemMetadata(itemId: self.data.itemId)
406 let traitsView = metadata != nil ? MetadataViews.dictToTraits(dict: metadata!, excludedNames: []) : nil
407 return traitsView
408 }
409 return nil
410 }
411
412 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
413 return <-TuneGO.createEmptyCollection(nftType: Type<@TuneGO.NFT>())
414 }
415 }
416
417 // Admin is an authorization resource that allows the owner to modify
418 // various aspects of the Items, Sets, and Collectibles
419 access(all) resource Admin {
420 // Create a new Item struct and store it in the Items dictionary in the contract
421 access(all) fun createItem(metadata: {String: String}): UInt32 {
422 var newItem = Item(metadata: metadata)
423 let newId = newItem.itemId
424
425 TuneGO.itemDatas[newId] = newItem
426
427 return newId
428 }
429
430 // Create a new Set resource and store it in the sets mapping in the contract
431 access(all) fun createSet(name: String, description: String?) {
432 var newSet <- create Set(name: name, description: description)
433 TuneGO.sets[newSet.setId] <-! newSet
434 }
435
436 // Return a reference to a set in the contract
437 access(all) fun borrowSet(setId: UInt32): &Set {
438 pre {
439 TuneGO.sets[setId] != nil: "Cannot borrow set: The set doesn't exist."
440 }
441
442 return (&TuneGO.sets[setId] as &Set?)!
443 }
444
445 // End the current series and start a new one
446 access(all) fun startNewSeries(): UInt32 {
447 TuneGO.currentSeries = TuneGO.currentSeries + UInt32(1)
448
449 emit NewSeriesStarted(newCurrentSeries: TuneGO.currentSeries)
450
451 return TuneGO.currentSeries
452 }
453
454 // Create a new Admin resource
455 access(all) fun createNewAdmin(): @Admin {
456 return <-create Admin()
457 }
458 }
459
460 // Interface that users can cast their TuneGO Collection as
461 // to allow others to deposit TuneGO Collectibles into their Collection.
462 access(all) resource interface TuneGOCollectionPublic: NonFungibleToken.Receiver, ViewResolver.ResolverCollection {
463 access(all) fun deposit(token: @{NonFungibleToken.NFT})
464 access(all) fun batchDeposit(tokens: @{NonFungibleToken.Collection})
465 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}?
466 access(all) view fun borrowCollectible(_ id: UInt64): &TuneGO.NFT? {
467 // If the result isn't nil, the id of the returned reference
468 // should be the same as the argument to the function
469 post {
470 (result == nil) || (result?.id == id):
471 "Cannot borrow collectible reference: The id of the returned reference is incorrect."
472 }
473 }
474 access(all) view fun getSupportedNFTTypes(): {Type: Bool}
475 access(all) view fun isSupportedNFTType(type: Type): Bool
476 }
477
478 // Collection is a resource that every user who owns NFTs
479 // will store in their account to manage their NFTS
480 access(all) resource Collection: NonFungibleToken.Collection, TuneGOCollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic, ViewResolver.ResolverCollection {
481 access(all) event ResourceDestroyed()
482 // Dictionary of Collectible conforming tokens
483 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
484
485 init() {
486 self.ownedNFTs <- {}
487 }
488
489 /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
490 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
491 let supportedTypes: {Type: Bool} = {}
492 supportedTypes[Type<@TuneGO.NFT>()] = true
493 return supportedTypes
494 }
495
496 /// Returns whether or not the given type is accepted by the collection
497 /// A collection that can accept any type should just return true by default
498 access(all) view fun isSupportedNFTType(type: Type): Bool {
499 if type == Type<@TuneGO.NFT>() {
500 return true
501 }
502 return false
503 }
504
505 // Remove a Collectible from the Collection and moves it to the caller
506 access(NonFungibleToken.Withdraw)
507 fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
508
509 let token <- self.ownedNFTs.remove(key: withdrawID)
510 ?? panic("Cannot withdraw: Collectible does not exist in the collection.")
511
512 emit Withdraw(id: token.id, from: self.owner?.address)
513
514 return <-token
515 }
516
517 // Withdraw multiple tokens and returns them as a Collection
518 access(NonFungibleToken.Withdraw)
519 fun batchWithdraw(ids: [UInt64]): @{NonFungibleToken.Collection} {
520 var batchCollection <- create Collection()
521
522 for id in ids {
523 batchCollection.deposit(token: <-self.withdraw(withdrawID: id))
524 }
525
526 return <-batchCollection
527 }
528
529 // Add a Collectible to the Collections dictionary
530 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
531
532 // Cast the deposited token as a Collectible NFT to make sure
533 // it is the correct type
534 let token <- token as! @TuneGO.NFT
535
536 let id = token.id
537
538 let oldToken <- self.ownedNFTs[id] <- token
539
540 // Emit a deposit event if the Collection is in an account's storage
541 emit Deposit(id: id, to: self.owner?.address)
542
543 // Destroy the empty removed token
544 destroy oldToken
545 }
546
547 // Deposit multiple NFTs into this Collection
548 access(all) fun batchDeposit(tokens: @{NonFungibleToken.Collection}) {
549
550 let keys = tokens.getIDs()
551
552 for key in keys {
553 self.deposit(token: <-tokens.withdraw(withdrawID: key))
554 }
555
556 // Destroy the empty Collection
557 destroy tokens
558 }
559
560 // Get the Ids that are in the Collection
561 access(all) view fun getIDs(): [UInt64] {
562 return self.ownedNFTs.keys
563 }
564
565 // Gets the amount of NFTs stored in the collection
566 access(all) view fun getLength(): Int {
567 return self.ownedNFTs.keys.length
568 }
569
570 // Return a borrowed reference to a Collectible in the Collection
571 // This only allows the caller to read the ID of the NFT,
572 // not any Collectible specific data.
573 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
574 return &self.ownedNFTs[id] as &{NonFungibleToken.NFT}?
575 }
576
577 // Return a borrowed reference to a Collectible
578 // This allows the caller to read the setId, itemId, serialNumber,
579 // and use them to read the setData or Item data from the contract
580 access(all) view fun borrowCollectible(_ id: UInt64): &TuneGO.NFT? {
581 if self.ownedNFTs[id] != nil {
582 return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}? as! &TuneGO.NFT?)
583 } else {
584 return nil
585 }
586 }
587
588 access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
589 if let nft = &self.ownedNFTs[id] as &{NonFungibleToken.NFT}? {
590 return nft as &{ViewResolver.Resolver}
591 }
592 return nil
593 }
594
595 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
596 return <-create TuneGO.Collection()
597 }
598 }
599
600 // -----------------------------------------------------------------------
601 // TuneGO contract-level function definitions
602 // -----------------------------------------------------------------------
603
604 // Create a new, empty Collection object so that a user can store it in their account storage
605 // and be able to receive Collectibles
606 access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
607 assert(nftType == Type<@TuneGO.NFT>(), message: "I don't know how to create ".concat(nftType.identifier))
608 return <-create TuneGO.Collection()
609 }
610
611 access(all) view fun getContractViews(resourceType: Type?): [Type] {
612 return [
613 Type<MetadataViews.NFTCollectionData>(),
614 Type<MetadataViews.NFTCollectionDisplay>()
615 ]
616 }
617
618 access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
619 switch viewType {
620 case Type<MetadataViews.NFTCollectionData>():
621 return MetadataViews.NFTCollectionData(
622 storagePath: TuneGO.CollectionStoragePath,
623 publicPath: TuneGO.CollectionPublicPath,
624 publicCollection: Type<&TuneGO.Collection>(),
625 publicLinkedType: Type<&TuneGO.Collection>(),
626 createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} {
627 return <-TuneGO.createEmptyCollection(nftType: Type<@TuneGO.NFT>())
628 })
629 )
630 case Type<MetadataViews.NFTCollectionDisplay>():
631 let media = MetadataViews.Media(
632 file: MetadataViews.HTTPFile(
633 url: "https://tunegonft.com/assets/images/collections-page/tunekitties.png"
634 ),
635 mediaType: "image/png"
636 )
637 let socials: {String:MetadataViews.ExternalURL} = {}
638 return MetadataViews.NFTCollectionDisplay(
639 name: "TuneKitties",
640 description: "Deep in the clubs and streets of the metaverse TuneKitties prowl with the purrfect mix of sound and style. Limited edition NFTs by TuneGO.",
641 externalURL: MetadataViews.ExternalURL("https://www.tunegonft.com/collection-details/98434c03-17e3-4e9a-9f6b-3b786a4fad6e"),
642 squareImage: media,
643 bannerImage: media,
644 socials: socials
645 )
646 }
647 return nil
648 }
649
650
651 // Return all the Collectible Items
652 access(all) fun getAllItems(): [TuneGO.Item] {
653 return TuneGO.itemDatas.values
654 }
655
656 // Get all metadata of an Item
657 access(all) fun getItemMetadata(itemId: UInt32): {String: String}? {
658 return self.itemDatas[itemId]?.metadata
659 }
660
661 // Get a metadata field of an Item
662 access(all) fun getItemMetadataByField(itemId: UInt32, field: String): String? {
663 if let item = TuneGO.itemDatas[itemId] {
664 return item.metadata[field]
665 } else {
666 return nil
667 }
668 }
669
670 // Get the name of the Set
671 access(all) fun getSetName(setId: UInt32): String? {
672 return TuneGO.setDatas[setId]?.name
673 }
674
675 // Get the description of the Set
676 access(all) fun getSetDescription(setId: UInt32): String? {
677 return TuneGO.setDatas[setId]?.description
678 }
679
680 // Get the series that the specified Set is associated with
681 access(all) fun getSetSeries(setId: UInt32): UInt32? {
682 return TuneGO.setDatas[setId]?.series
683 }
684
685 // Get the Ids that the specified Set name is associated with
686 access(all) fun getSetIdsByName(setName: String): [UInt32]? {
687 var setIds: [UInt32] = []
688
689 for setData in TuneGO.setDatas.values {
690 if setName == setData.name {
691 setIds.append(setData.setId)
692 }
693 }
694
695 if setIds.length == 0 {
696 return nil
697 } else {
698 return setIds
699 }
700 }
701
702 // Get the list of Item Ids that are in the Set
703 access(all) fun getItemsInSet(setId: UInt32): [UInt32]? {
704 return TuneGO.sets[setId]?.items
705 }
706
707 // Indicates if a Set/Item combo (otherwise known as an edition) is retired
708 access(all) fun isEditionRetired(setId: UInt32, itemId: UInt32): Bool? {
709 if let setToRead <- TuneGO.sets.remove(key: setId) {
710 let retired = setToRead.retired[itemId]
711 TuneGO.sets[setId] <-! setToRead
712 return retired
713 } else {
714 return nil
715 }
716 }
717
718 // Indicates if the Set is locked or not
719 access(all) fun isSetLocked(setId: UInt32): Bool? {
720 return TuneGO.sets[setId]?.locked
721 }
722
723 // Total number of Collectibles that have been minted from an edition
724 access(all) fun getNumberCollectiblesInEdition(setId: UInt32, itemId: UInt32): UInt32? {
725 if let setToRead <- TuneGO.sets.remove(key: setId) {
726 let amount = setToRead.numberMintedPerItem[itemId]
727
728 // Put the Set back into the Sets dictionary
729 TuneGO.sets[setId] <-! setToRead
730
731 return amount
732 } else {
733 return nil
734 }
735 }
736
737 // -----------------------------------------------------------------------
738 // TuneGO initialization function
739 // -----------------------------------------------------------------------
740
741 init() {
742 // Paths
743 self.CollectionPublicPath= /public/TuneGOCollection
744 self.CollectionStoragePath= /storage/TuneGOCollection
745 self.AdminPublicPath= /public/TuneGOAdmin
746 self.AdminStoragePath=/storage/TuneGOAdmin
747
748 self.currentSeries = 0
749 self.itemDatas = {}
750 self.setDatas = {}
751 self.sets <- {}
752 self.nextItemId = 1
753 self.nextSetId = 1
754 self.totalSupply = 0
755
756 // Put a new Collection in storage
757 self.account.storage.save<@Collection>(<- create Collection(), to: TuneGO.CollectionStoragePath)
758
759 // Create a public capability for the Collection
760 self.account.capabilities.publish(
761 self.account.capabilities.storage.issue<&{TuneGOCollectionPublic}>(TuneGO.CollectionStoragePath),
762 at: TuneGO.CollectionPublicPath
763 )
764
765 // Put the Admin in storage
766 self.account.storage.save<@Admin>(<- create Admin(), to: TuneGO.AdminStoragePath)
767
768 emit ContractInitialized()
769 }
770}