Smart Contract
OlympicPin
A.1d007eed492fdbbe.OlympicPin
1import NonFungibleToken from 0x1d7e57aa55817448
2import ViewResolver from 0x1d7e57aa55817448
3
4access(all) contract OlympicPin : NonFungibleToken {
5
6 // The total number of Cards in existence
7 access(all) var totalSupply: UInt64
8
9
10
11 // Emitted when a new Pin struct is created
12 access(all) event PinCreated(id: UInt32, metadata: {String:String})
13
14 // Emitted when a new series has been triggered by an admin
15 access(all) event NewSeriesStarted(newCurrentSeries: UInt32)
16
17 // Emitted when a new Set is created
18 access(all) event SetCreated(setId: UInt32, series: UInt32, name: String)
19
20 // Emitted when a new Pin is added to a Set
21 access(all) event PinAddedToSet(setId: UInt32, pinId: UInt32)
22 // Emitted when a Pin is retired from a Set and cannot be used to mint
23 access(all) event PinRetiredFromSet(setId: UInt32, pinId: UInt32, numPieces: UInt32)
24 // Emitted when a Set is locked, meaning pins cannot be added
25 access(all) event SetLocked(setId: UInt32)
26 // Emitted when a Piece is minted from a Set
27 access(all) event PieceMinted(pieceId: UInt64, pinId: UInt32, setId: UInt32, serialNumber: UInt32)
28
29 // Events for Collection-related actions
30 //
31 // Emitted when a piece is withdrawn from a Collection
32
33 access(all) event Withdraw(id: UInt64, from: Address?)
34
35 // Emitted when a piece is deposited into a Collection
36 access(all) event Deposit(id: UInt64, to: Address?)
37
38 // Emitted when a Piece is destroyed
39 access(all) event PieceDestroyed(id: UInt64)
40
41 // -----------------------------------------------------------------------
42 // OlympicPin contract-level fields.
43 // These contain actual values that are stored in the smart contract.
44 // -----------------------------------------------------------------------
45
46 // Series that this Set belongs to.
47 // Series is a concept that indicates a group of Sets through time.
48 // Many Sets can exist at a time, but only one series.
49 access(all) var currentSeries: UInt32
50
51 // Variable size dictionary of Pin structs
52 access(self) var pins: {UInt32: Pin}
53
54 // Variable size dictionary of SetData structs
55 access(self) var setDatas: {UInt32: SetData}
56
57 // Variable size dictionary of Set resources
58 access(self) var sets: @{UInt32: Set}
59
60 // The Id that is used to create pins.
61 // Every time a Pin is created, pinId is assigned
62 // to the new Pin's Id and then is incremented by 1.
63 access(all) var nextPinId: UInt32
64
65 // The Id that is used to create SetDatas.
66 // Every time a SetData is created, SetId is assigned
67 // to the new SetData's Id and then is incremented by 1.
68 access(all) var nextSetId: UInt32
69
70 access(all) let CollectionStoragePath: StoragePath
71 access(all) let CollectionPublicPath: PublicPath
72 access(all) let AdminStoragePath: StoragePath
73
74 //Pin
75 //
76 access(all) struct Pin {
77 access(all) let pinId: UInt32
78
79 access(all) let metadata: {String: String}
80
81 init(metadata: {String: String}){
82
83 pre {
84 metadata.length != 0: "New Pin metadata cannot be empty"
85 }
86
87 self.pinId = OlympicPin.nextPinId
88 self.metadata = metadata
89 }
90 }
91
92 //SetData
93 //
94
95 access(all) struct SetData {
96
97 // Unique Id for the Set
98 access(all) let setId: UInt32
99
100 // Name of the Set
101 access(all) let name: String
102
103 // Series that this Set belongs to.
104 // Series is a concept that indicates a group of Sets through time.
105 // Many Sets can exist at a time, but only one series.
106 access(all) let series: UInt32
107
108 init(name: String) {
109 pre {
110 name.length > 0: "New Set name cannot be empty"
111 }
112 self.setId = OlympicPin.nextSetId
113 self.name = name
114 self.series = OlympicPin.currentSeries
115 }
116 }
117
118 // Set is a resource type that contains the functions to add and remove
119 // pins from a set and mint NFTs.
120 //
121 // It is stored in a private field in the contract so that
122 // the admin resource can call its methods.
123 //
124 // The admin can add pins to a Set so that the set can mint NFTs
125 // that reference that PinId.
126 // The NFTs that are minted by a Set will be listed as belonging to
127 // the Set that minted it, as well as the Pin it references.
128 //
129 // Admin can also retire pins from the Set, meaning that the retired
130 // Pin can no longer have NFTs minted from it.
131 //
132 // If the admin locks the Set, no more pins can be added to it, but
133 // NFTs can still be minted.
134 //
135 // If retireAll() and lock() are called back-to-back,
136 // the Set is closed off forever and nothing more can be done with it.
137 access(all) resource Set {
138
139 // Unique Id for the set
140 access(all) let setId: UInt32
141
142 // Array of pins that are a part of this set.
143 // When a Pin is added to the set, its Id gets appended here.
144 // The Id does not get removed from this array when a Pin is retired.
145 access(contract) var pins: [UInt32]
146
147 // Map of Pin Ids that Indicates if a Pin in this Set can be minted.
148 // When a Pin is added to a Set, it is mapped to false (not retired).
149 // When a Pin is retired, this is set to true and cannot be changed.
150 access(contract) var retired: {UInt32: Bool}
151
152 // Indicates if the Set is currently locked.
153 // When a Set is created, it is unlocked
154 // and pins are allowed to be added to it.
155 // When a set is locked, pins cannot be added.
156 // A Set can never be changed from locked to unlocked,
157 // the decision to lock a Set it is final.
158 // If a Set is locked, pins cannot be added, but
159 // Pieces can still be minted from pins
160 // that exist in the Set.
161 access(all) var locked: Bool
162
163 // Mapping of Pin Ids that indicates the number of Pieces
164 // that have been minted for specific pins in this Set.
165 // When a Piece is minted, this value is stored in the Piece to
166 access(contract) var numberMintedPerPin: {UInt32: UInt32}
167
168 init(name: String) {
169 self.setId = OlympicPin.nextSetId
170 self.pins = []
171 self.retired = {}
172 self.locked = false
173 self.numberMintedPerPin = {}
174
175 // Create a new SetData for this Set and store it in contract storage
176 OlympicPin.setDatas[self.setId] = SetData(name: name)
177 }
178
179 // addPin adds a pin to the set
180 //
181 // Parameters: pinId: The Id of the Pin that is being added
182 //
183 // Pre-Conditions:
184 // The Pin needs to be an existing Pin
185 // The Set needs to be not locked
186 // The Pin can't have already been added to the Set
187 //
188 access(all) fun addPin(pinId: UInt32) {
189 pre {
190 OlympicPin.pins[pinId] != nil: "Cannot add the Pin to Set: Pin doesn't exist."
191 !self.locked: "Cannot add the Pin to the Set after the set has been locked."
192 self.numberMintedPerPin[pinId] == nil: "The pin has already been added to the set."
193 }
194
195 // Add the Pin to the array of pins
196 self.pins.append(pinId)
197
198 // Open the Pin up for minting
199 self.retired[pinId] = false
200
201 // Initialize the Piece count to zero
202 self.numberMintedPerPin[pinId] = 0
203
204 emit PinAddedToSet(setId: self.setId, pinId: pinId)
205 }
206
207 // addPins adds multiple pins to the Set
208 //
209 // Parameters: pinIds: The Ids of the pins that are being added
210 // as an array
211 //
212 access(all) fun addPins(pinIds: [UInt32]) {
213 for pinId in pinIds {
214 self.addPin(pinId: pinId)
215 }
216 }
217
218 // retirePin retires a Pin from the Set so that it can't mint new Piece
219 //
220 // Parameters: pinId: The Id of the Pin that is being retired
221 //
222 // Pre-Conditions:
223 // The Pin is part of the Set and not retired (available for minting).
224 //
225 access(all) fun retirePin(pinId: UInt32) {
226 pre {
227 self.retired[pinId] != nil: "Cannot retire the Pin: Pin doesn't exist in this set!"
228 }
229
230 if !self.retired[pinId]! {
231 self.retired[pinId] = true
232
233 emit PinRetiredFromSet(setId: self.setId, pinId: pinId, numPieces: self.numberMintedPerPin[pinId]!)
234 }
235 }
236
237 // retireAll retires all the pins in the Set
238 // Afterwards, none of the retired pins will be able to mint new NFT
239 //
240 access(all) fun retireAll() {
241 for pinId in self.pins {
242 self.retirePin(pinId: pinId)
243 }
244 }
245
246 // lock() locks the Set so that no more pins can be added to it
247 //
248 // Pre-Conditions:
249 // The Set should not be locked
250 access(all) fun lock() {
251 if !self.locked {
252 self.locked = true
253 emit SetLocked(setId: self.setId)
254 }
255 }
256
257 // mintPiece mints a new and returns the newly minted Piece
258 //
259 // Parameters: pinId: The ID of the Pin that the Piece references
260 //
261 // Pre-Conditions:
262 // The Pin must exist in the Set and be allowed to mint new Pieces
263 //
264 // Returns: The NFT that was minted
265 //
266 access(all) fun mintPiece(pinId: UInt32): @NFT {
267 pre {
268 self.retired[pinId] != nil: "Cannot mint the Piece: This pin doesn't exist."
269 !self.retired[pinId]!: "Cannot mint the Piece from this pin: This pin has been retired."
270 }
271
272 // Gets the number of Pieces that have been minted for this Pin
273 // to use as this Piece's serial number
274 let numInPin = self.numberMintedPerPin[pinId]!
275
276 // Mint the new Piece
277 let newPiece: @NFT <- create NFT(pinId: pinId, setId: self.setId, serialNumber: numInPin + UInt32(1))
278
279 // Increment the count of Pieces minted for this Pin
280 self.numberMintedPerPin[pinId] = numInPin + UInt32(1)
281
282 return <-newPiece
283 }
284
285 // batchMintPiece mints an arbitrary quantity of Pieces
286 // and returns them as a Collection
287 //
288 // Parameters: pinId: the ID of the Pin that the Pieces are minted for
289 // quantity: The quantity of Pieces to be minted
290 //
291 // Returns: Collection object that contains all the Pieces that were minted
292 //
293 access(all) fun batchMintPiece(pinId: UInt32, quantity: UInt64): @Collection {
294 let newCollection <- create Collection()
295
296 var i: UInt64 = 0
297 while i < quantity {
298 newCollection.deposit(token: <-self.mintPiece(pinId: pinId))
299 i = i + UInt64(1)
300 }
301
302 return <-newCollection
303 }
304
305 access(all) view fun getPins(): [UInt32] {
306 return self.pins
307 }
308
309 access(all) view fun getRetired(): {UInt32: Bool} {
310 return self.retired
311 }
312
313 access(all) view fun getNumMintedPerPlay(): {UInt32: UInt32} {
314 return self.numberMintedPerPin
315 }
316 }
317
318 access(all) struct PieceData {
319
320 access(all) let pinId: UInt32
321 access(all) let setId: UInt32
322 access(all) let serialNumber: UInt32
323
324 init(pinId: UInt32, setId: UInt32, serialNumber: UInt32) {
325 self.pinId = pinId
326 self.setId = setId
327 self.serialNumber = serialNumber
328 }
329 }
330
331 access(all) resource NFT: NonFungibleToken.NFT {
332
333 // Global unique Piece Id
334 access(all) let id: UInt64
335
336 // Struct of Piece metadata
337 access(all) let data: PieceData
338
339 access(all) view fun getViews(): [Type] {
340 return []
341 }
342
343 access(all) fun resolveView(_ view: Type): AnyStruct? {
344 return nil
345 }
346
347 init(pinId: UInt32, setId: UInt32, serialNumber: UInt32) {
348
349 // Increment the global Piece Ids
350 OlympicPin.totalSupply = OlympicPin.totalSupply + UInt64(1)
351
352 self.id = OlympicPin.totalSupply
353
354 self.data = PieceData(pinId: pinId, setId: setId, serialNumber: serialNumber)
355
356 emit PieceMinted(pieceId: self.id, pinId: self.data.pinId, setId: self.data.setId, serialNumber: self.data.serialNumber)
357 }
358
359 // If the Piece is destroyed, emit an event to indicate
360 // to outside observers that it has been destroyed
361 access(all) event ResourceDestroyed(
362 id: UInt64 = self.id,
363 serialNumber: UInt32 = self.data.serialNumber,
364 pinId: UInt32 = self.data.pinId,
365 setId: UInt32 = self.data.setId
366 )
367
368 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
369 return <- OlympicPin.createEmptyCollection(nftType: Type<@OlympicPin.NFT>())
370 }
371 }
372
373 access(all) resource Admin {
374 // createPin creates a new Pin struct
375 // and stores it in the pins dictionary in the Olympic smart contract
376 //
377 // Parameters: metadata: A dictionary mapping metadata titles to their data
378 //
379 // Returns: the Id of the new Pin object
380 //
381 access(all) fun createPin(metadata: {String: String}): UInt32 {
382 // Create the new Pin
383 var newPin: OlympicPin.Pin = Pin(metadata: metadata)
384 let newId: UInt32 = newPin.pinId
385
386 // Increment nextPinId
387 OlympicPin.nextPinId = OlympicPin.nextPinId + UInt32(1)
388 emit PinCreated(id: newId, metadata: metadata)
389
390 // Store it in the contract storage
391 OlympicPin.pins[newId] = newPin
392 return newId
393 }
394
395 // createSet creates a new Set struct
396 // and stores it in the Sets dictionary in the Olympic smart contract
397 //
398 // Parameters: metadata: A dictionary mapping metadata titles to their data
399 //
400 // Returns: the Id of the new SetData object
401 //
402 access(all) fun createSet(name: String): UInt32 {
403
404 // Create the new Set
405 var newSet <- create Set(name: name)
406 let newId = newSet.setId
407
408 // Increment the setId
409 OlympicPin.nextSetId = OlympicPin.nextSetId + UInt32(1)
410 emit SetCreated(setId: newId, series: OlympicPin.currentSeries, name: name)
411
412 // Store it in the sets mapping field
413 OlympicPin.sets[newId] <-! newSet
414 return newId
415 }
416
417 // borrowSet returns a reference to a set in the OlympicPin
418 // contract so that the admin can call methods on it
419 //
420 // Parameters: setId: The Id of the Set that you want to
421 // get a reference to
422 //
423 // Returns: A reference to the Set with all of the fields
424 // and methods exposed
425 //
426 access(all) view fun borrowSet(setId: UInt32): &Set {
427 pre {
428 OlympicPin.sets[setId] != nil: "Cannot borrow Set: The Set doesn't exist"
429 }
430
431 // Get a reference to the Set and return it
432 // use `&` to indicate the reference to the object and type
433 return (&OlympicPin.sets[setId] as &Set?)!
434 }
435
436 // startNewSeries ends the current series by incrementing
437 // the series number, meaning that Pieces minted after this
438 // will use the new series number
439 //
440 // Returns: The new series number
441 //
442 access(all) fun startNewSeries(): UInt32 {
443 // End the current series and start a new one
444 // by incrementing the OlympicPin series number
445 OlympicPin.currentSeries = OlympicPin.currentSeries + UInt32(1)
446
447 emit NewSeriesStarted(newCurrentSeries: OlympicPin.currentSeries)
448
449 return OlympicPin.currentSeries
450 }
451
452 // createNewAdmin creates a new Admin resource
453 //
454 access(all) fun createNewAdmin(): @Admin {
455 return <-create Admin()
456 }
457 }
458
459 access(all) resource interface PieceCollectionPublic : NonFungibleToken.CollectionPublic {
460 access(all) fun batchDeposit(tokens: @{NonFungibleToken.Collection}): Void
461 access(all) fun borrowPiece(id: UInt64): &OlympicPin.NFT? {
462 post {
463 result == nil || result?.id == id:
464 "Cannot borrow Piece reference: The Id of the returned reference is incorrect"
465 }
466 }
467 }
468
469 access(all) resource Collection: PieceCollectionPublic, NonFungibleToken.Collection {
470
471 // Keep track of all the NFTs that a user owns from this contract.
472 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
473
474 init () {
475 self.ownedNFTs <- {}
476 }
477
478 // Return a list of NFT types that this receiver accepts
479 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
480 let supportedTypes: {Type: Bool} = {}
481 supportedTypes[Type<@OlympicPin.NFT>()] = true
482 return supportedTypes
483 }
484
485 // Return whether or not the given type is accepted by the collection
486 // A collection that can accept any type should just return true by default
487 access(all) view fun isSupportedNFTType(type: Type): Bool {
488 if type == Type<@OlympicPin.NFT>() {
489 return true
490 }
491 return false
492 }
493
494 // Return the amount of NFTs stored in the collection
495 access(all) view fun getLength(): Int {
496 return self.ownedNFTs.length
497 }
498
499 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection}{
500 return <- OlympicPin.createEmptyCollection(nftType: Type<@OlympicPin.NFT>())
501 }
502
503 access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
504 // Remove the nft from the Collection
505 let token <- self.ownedNFTs.remove(key: withdrawID)
506 ?? panic("Cannot withdraw: Piece does not exist in the collection")
507
508 emit Withdraw(id: token.id, from: self.owner?.address)
509
510 // Return the withdrawn token
511 return <-token
512 }
513
514 // batchWithdraw withdraws multiple tokens and returns them as a Collection
515 //
516 // Parameters: ids: An array of IDs to withdraw
517 //
518 // Returns: @NonFungibleToken.Collection: A collection that contains
519 // the withdrawn pieces
520 //
521 access(NonFungibleToken.Withdraw) fun batchWithdraw(ids: [UInt64]): @{NonFungibleToken.Collection} {
522 // Create a new empty Collection
523 var batchCollection <- create Collection()
524
525 // Iterate through the ids and withdraw them from the Collection
526 for id in ids {
527 batchCollection.deposit(token: <-self.withdraw(withdrawID: id))
528 }
529
530 // Return the withdrawn tokens
531 return <-batchCollection
532 }
533
534 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
535 let token <- token as! @OlympicPin.NFT
536 let id = token.id
537
538 // add the new token to the dictionary which removes the old one
539 let oldToken <- self.ownedNFTs[id] <- token
540
541 // Only emit a deposit event if the Collection
542 // is in an account's storage
543 if self.owner?.address != nil {
544 emit Deposit(id: id, to: self.owner?.address)
545 }
546 destroy oldToken
547 }
548
549 // batchDeposit takes a Collection object as an argument
550 // and deposits each contained NFT into this Collection
551 access(all) fun batchDeposit(tokens: @{NonFungibleToken.Collection}) {
552
553 // Get an array of the IDs to be deposited
554 let keys = tokens.getIDs()
555
556 // Iterate through the keys in the collection and deposit each one
557 for key in keys {
558 self.deposit(token: <-tokens.withdraw(withdrawID: key))
559 }
560
561 // Destroy the empty Collection
562 destroy tokens
563 }
564
565 access(all) view fun getIDs(): [UInt64] {
566 return self.ownedNFTs.keys
567 }
568
569 access(all) view fun borrowNFT(_ id: UInt64) : &{NonFungibleToken.NFT}? {
570 return &self.ownedNFTs[id]
571 }
572
573 // borrowPiece returns a borrowed reference to a Piece
574 // so that the caller can read data and call methods from it.
575 // They can use this to read its setID, pinID, serialNumber,
576 // or any of the setData or Pin data associated with it by
577 // getting the setID or pinID and reading those fields from
578 // the smart contract.
579 //
580 // Parameters: id: The ID of the NFT to get the reference for
581 //
582 // Returns: A reference to the NFT
583 access(all) view fun borrowPiece(id: UInt64): &OlympicPin.NFT? {
584 return self.borrowNFT(id) as! &OlympicPin.NFT?
585 }
586
587 access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
588 if let nft = &self.ownedNFTs[id] as &{NonFungibleToken.NFT}? {
589 return nft as &{ViewResolver.Resolver}
590 }
591 return nil
592 }
593 }
594
595 // -----------------------------------------------------------------------
596 // OlympicPin contract-level function definitions
597 // -----------------------------------------------------------------------
598
599 // createEmptyCollection creates a new, empty Collection object so that
600 // a user can store it in their account storage.
601 // Once they have a Collection in their storage, they are able to receive
602 // Pieces in transactions.
603 //
604 access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
605 if nftType != Type<@OlympicPin.NFT>() {
606 panic("NFT type is not supported")
607 }
608 return <-create OlympicPin.Collection()
609 }
610
611 // getAllPins returns all the pins in OlympicPin
612 //
613 // Returns: An array of all the pins that have been created
614 access(all) view fun getAllPins(): [OlympicPin.Pin] {
615 return OlympicPin.pins.values
616 }
617
618 // getPinMetaData returns all the metadata associated with a specific Pin
619 //
620 // Parameters: pinId: The id of the Pin that is being searched
621 //
622 // Returns: The metadata as a String to String mapping optional
623 access(all) view fun getPinMetaData(pinId: UInt32): {String: String}? {
624 return self.pins[pinId]?.metadata
625 }
626
627 // getPinMetaDataByField returns the metadata associated with a
628 // specific field of the metadata
629 //
630 // Parameters: pinId: The id of the Pin that is being searched
631 // field: The field to search for
632 //
633 // Returns: The metadata field as a String Optional
634 access(all) view fun getPinMetaDataByField(pinId: UInt32, field: String): String? {
635 // Don't force a revert if the pinId or field is invalid
636 if let pin = OlympicPin.pins[pinId] {
637 return pin.metadata[field]
638 } else {
639 return nil
640 }
641 }
642
643 // getSetName returns the name that the specified Set
644 // is associated with.
645 //
646 // Parameters: setId: The id of the Set that is being searched
647 //
648 // Returns: The name of the Set
649 access(all) view fun getSetName(setId: UInt32): String? {
650 // Don't force a revert if the setId is invalid
651 return OlympicPin.setDatas[setId]?.name
652 }
653
654 // getSetSeries returns the series that the specified Set
655 // is associated with.
656 //
657 // Parameters: setId: The id of the Set that is being searched
658 //
659 // Returns: The series that the Set belongs to
660 access(all) view fun getSetSeries(setId: UInt32): UInt32? {
661 // Don't force a revert if the setId is invalid
662 return OlympicPin.setDatas[setId]?.series
663 }
664
665 // getSetIdsByName returns the Ids that the specified Set name
666 // is associated with.
667 //
668 // Parameters: setName: The name of the Set that is being searched
669 //
670 // Returns: An array of the Ids of the Set if it exists, or nil if doesn't
671 access(all) fun getSetIdsByName(setName: String): [UInt32]? {
672 var setIds: [UInt32] = []
673
674 // Iterate through all the setDatas and search for the name
675 for setData in OlympicPin.setDatas.values {
676 if setName == setData.name {
677 // If the name is found, return the Id
678 setIds.append(setData.setId)
679 }
680 }
681
682 // If the name isn't found, return nil
683 // Don't force a revert if the setName is invalid
684 if setIds.length == 0 {
685 return nil
686 } else {
687 return setIds
688 }
689 }
690
691 // getPinsInSet returns the list of Pin Ids that are in the Set
692 //
693 // Parameters: setId: The id of the Set that is being searched
694 //
695 // Returns: An array of Pin Ids
696 access(all) view fun getPinsInSet(setId: UInt32): [UInt32]? {
697 // Don't force a revert if the setId is invalid
698 return OlympicPin.sets[setId]?.pins
699 }
700
701 // isEditionRetired returns a boolean that indicates if a Set/Pin combo
702 // (otherwise known as an edition) is retired.
703 // If an edition is retired, it still remains in the Set,
704 // but Pieces can no longer be minted from it.
705 //
706 // Parameters: setId: The id of the Set that is being searched
707 // pinId: The id of the Pin that is being searched
708 //
709 // Returns: Boolean indicating if the edition is retired or not
710 access(all) fun isEditionRetired(setId: UInt32, pinId: UInt32): Bool? {
711 if let retired = OlympicPin.sets[setId]?.retired {
712 let retired = retired[pinId]
713
714 // Return the retired status
715 return retired
716 } else {
717
718 // If the Set wasn't found, return nil
719 return nil
720 }
721 }
722
723 // isSetLocked returns a boolean that indicates if a Set
724 // is locked. If it's locked,
725 // new Pins can no longer be added to it,
726 // but NFTs can still be minted from Pins the set contains.
727 //
728 // Parameters: setId: The id of the Set that is being searched
729 //
730 // Returns: Boolean indicating if the Set is locked or not
731 access(all) view fun isSetLocked(setId: UInt32): Bool? {
732 // Don't force a revert if the setId is invalid
733 return OlympicPin.sets[setId]?.locked
734 }
735
736 // getNumPiecesInEdition return the number of Pieces that have been
737 // minted from a certain edition.
738 //
739 // Parameters: setId: The id of the Set that is being searched
740 // pinId: The id of the Pin that is being searched
741 //
742 // Returns: The total number of NFTs
743 // that have been minted from an edition
744 access(all) fun getNumPiecesInEdition(setId: UInt32, pinId: UInt32): UInt32? {
745 if let numberMintedPerPin = OlympicPin.sets[setId]?.numberMintedPerPin {
746 let amount = numberMintedPerPin[pinId]
747 return amount
748 } else {
749 return nil
750 }
751 }
752
753 access(all) view fun getContractViews(resourceType: Type?): [Type] {
754 return []
755 }
756
757 access(all) view fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
758 return nil
759 }
760
761 init() {
762 self.currentSeries = 0
763 self.pins = {}
764 self.setDatas = {}
765 self.sets <- {}
766 self.totalSupply = 0
767 self.nextPinId = 1
768 self.nextSetId = 1
769 self.CollectionStoragePath = /storage/PieceCollection
770 self.CollectionPublicPath = /public/PieceCollection
771 self.AdminStoragePath = /storage/OlympicPinAdmin
772
773 // Put a new Collection in storage
774 self.account.storage.save<@Collection>(<-create Collection(), to: self.CollectionStoragePath)
775
776 // Create a public capability for the Collection
777 var cap = self.account.capabilities.storage.issue<&{PieceCollectionPublic}>(self.CollectionStoragePath)
778 self.account.capabilities.publish(cap, at: self.CollectionPublicPath)
779
780 // Create a Admin resource and save it to storage
781 self.account.storage.save<@Admin>(<-create Admin(), to: self.AdminStoragePath)
782 }
783}