@flowtyio/flow-contracts 0.1.0-beta.9 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +1 -1
  2. package/contracts/FungibleTokenSwitchboard.cdc +360 -0
  3. package/contracts/MetadataViews.cdc +79 -6
  4. package/contracts/NonFungibleToken.cdc +17 -10
  5. package/contracts/capability-cache/CapabilityCache.cdc +97 -0
  6. package/contracts/dapper/TopShot.cdc +323 -259
  7. package/contracts/dapper/TopShotLocking.cdc +41 -15
  8. package/contracts/dapper/offers/DapperOffersV2.cdc +46 -43
  9. package/contracts/dapper/offers/OffersV2.cdc +40 -56
  10. package/contracts/dapper/offers/Resolver.cdc +20 -13
  11. package/contracts/emerald-city/FLOAT.cdc +259 -254
  12. package/contracts/example/ExampleNFT.cdc +2 -2
  13. package/contracts/find/FindViews.cdc +357 -353
  14. package/contracts/flow-utils/ScopedFTProviders.cdc +5 -2
  15. package/contracts/flow-utils/ScopedNFTProviders.cdc +6 -2
  16. package/contracts/flowty-drops/ContractManager.cdc +73 -0
  17. package/contracts/flowty-drops/DropFactory.cdc +75 -0
  18. package/contracts/flowty-drops/DropTypes.cdc +282 -0
  19. package/contracts/flowty-drops/FlowtyActiveCheckers.cdc +113 -0
  20. package/contracts/flowty-drops/FlowtyAddressVerifiers.cdc +64 -0
  21. package/contracts/flowty-drops/FlowtyDrops.cdc +461 -0
  22. package/contracts/flowty-drops/FlowtyPricers.cdc +48 -0
  23. package/contracts/flowty-drops/initializers/ContractBorrower.cdc +14 -0
  24. package/contracts/flowty-drops/initializers/ContractInitializer.cdc +7 -0
  25. package/contracts/flowty-drops/initializers/OpenEditionInitializer.cdc +57 -0
  26. package/contracts/flowty-drops/nft/BaseCollection.cdc +97 -0
  27. package/contracts/flowty-drops/nft/BaseNFT.cdc +107 -0
  28. package/contracts/flowty-drops/nft/ContractFactory.cdc +13 -0
  29. package/contracts/flowty-drops/nft/ContractFactoryTemplate.cdc +48 -0
  30. package/contracts/flowty-drops/nft/NFTMetadata.cdc +140 -0
  31. package/contracts/flowty-drops/nft/OpenEditionNFT.cdc +42 -0
  32. package/contracts/flowty-drops/nft/OpenEditionTemplate.cdc +54 -0
  33. package/contracts/flowty-drops/nft/UniversalCollection.cdc +29 -0
  34. package/contracts/fungible-token-router/FungibleTokenRouter.cdc +103 -0
  35. package/contracts/hybrid-custody/CapabilityDelegator.cdc +28 -26
  36. package/contracts/hybrid-custody/CapabilityFactory.cdc +20 -18
  37. package/contracts/hybrid-custody/CapabilityFilter.cdc +41 -24
  38. package/contracts/hybrid-custody/HybridCustody.cdc +303 -242
  39. package/contracts/hybrid-custody/factories/FTAllFactory.cdc +16 -4
  40. package/contracts/hybrid-custody/factories/FTBalanceFactory.cdc +16 -4
  41. package/contracts/hybrid-custody/factories/FTProviderFactory.cdc +17 -5
  42. package/contracts/hybrid-custody/factories/FTReceiverBalanceFactory.cdc +16 -4
  43. package/contracts/hybrid-custody/factories/FTReceiverFactory.cdc +16 -4
  44. package/contracts/hybrid-custody/factories/FTVaultFactory.cdc +46 -0
  45. package/contracts/hybrid-custody/factories/NFTCollectionFactory.cdc +45 -0
  46. package/contracts/hybrid-custody/factories/NFTCollectionPublicFactory.cdc +16 -4
  47. package/contracts/hybrid-custody/factories/NFTProviderAndCollectionFactory.cdc +22 -0
  48. package/contracts/hybrid-custody/factories/NFTProviderFactory.cdc +16 -4
  49. package/contracts/lost-and-found/LostAndFound.cdc +21 -17
  50. package/flow.json +181 -7
  51. package/package.json +1 -1
  52. package/contracts/hybrid-custody/factories/NFTProviderAndCollectionPublicFactory.cdc +0 -10
@@ -47,62 +47,63 @@ import "FungibleToken"
47
47
  import "NonFungibleToken"
48
48
  import "MetadataViews"
49
49
  import "TopShotLocking"
50
+ import "ViewResolver"
50
51
 
51
- pub contract TopShot: NonFungibleToken {
52
+ access(all) contract TopShot: NonFungibleToken {
52
53
  // -----------------------------------------------------------------------
53
54
  // TopShot deployment variables
54
55
  // -----------------------------------------------------------------------
55
56
 
56
57
  // The network the contract is deployed on
57
- pub fun Network() : String { return "emulator" }
58
+ access(all) view fun Network() : String { return "emulator" }
58
59
 
59
60
  // The address to which royalties should be deposited
60
- pub fun RoyaltyAddress() : Address { return TopShot.account.address }
61
+ access(all) view fun RoyaltyAddress() : Address { return TopShot.account.address }
61
62
 
62
63
  // The path to the Subedition Admin resource belonging to the Account
63
64
  // which the contract is deployed on
64
- pub fun SubeditionAdminStoragePath() : StoragePath { return /storage/TopShotSubeditionAdmin}
65
+ access(all) view fun SubeditionAdminStoragePath() : StoragePath { return /storage/TopShotSubeditionAdmin}
65
66
 
66
67
  // -----------------------------------------------------------------------
67
68
  // TopShot contract Events
68
69
  // -----------------------------------------------------------------------
69
70
 
70
71
  // Emitted when the TopShot contract is created
71
- pub event ContractInitialized()
72
+ access(all) event ContractInitialized()
72
73
 
73
74
  // Emitted when a new Play struct is created
74
- pub event PlayCreated(id: UInt32, metadata: {String:String})
75
+ access(all) event PlayCreated(id: UInt32, metadata: {String:String})
75
76
  // Emitted when a new series has been triggered by an admin
76
- pub event NewSeriesStarted(newCurrentSeries: UInt32)
77
+ access(all) event NewSeriesStarted(newCurrentSeries: UInt32)
77
78
 
78
79
  // Events for Set-Related actions
79
80
  //
80
81
  // Emitted when a new Set is created
81
- pub event SetCreated(setID: UInt32, series: UInt32)
82
+ access(all) event SetCreated(setID: UInt32, series: UInt32)
82
83
  // Emitted when a new Play is added to a Set
83
- pub event PlayAddedToSet(setID: UInt32, playID: UInt32)
84
+ access(all) event PlayAddedToSet(setID: UInt32, playID: UInt32)
84
85
  // Emitted when a Play is retired from a Set and cannot be used to mint
85
- pub event PlayRetiredFromSet(setID: UInt32, playID: UInt32, numMoments: UInt32)
86
+ access(all) event PlayRetiredFromSet(setID: UInt32, playID: UInt32, numMoments: UInt32)
86
87
  // Emitted when a Set is locked, meaning Plays cannot be added
87
- pub event SetLocked(setID: UInt32)
88
+ access(all) event SetLocked(setID: UInt32)
88
89
  // Emitted when a Moment is minted from a Set
89
- pub event MomentMinted(momentID: UInt64, playID: UInt32, setID: UInt32, serialNumber: UInt32, subeditionID: UInt32)
90
+ access(all) event MomentMinted(momentID: UInt64, playID: UInt32, setID: UInt32, serialNumber: UInt32, subeditionID: UInt32)
90
91
 
91
92
  // Events for Collection-related actions
92
93
  //
93
94
  // Emitted when a moment is withdrawn from a Collection
94
- pub event Withdraw(id: UInt64, from: Address?)
95
+ access(all) event Withdraw(id: UInt64, from: Address?)
95
96
  // Emitted when a moment is deposited into a Collection
96
- pub event Deposit(id: UInt64, to: Address?)
97
+ access(all) event Deposit(id: UInt64, to: Address?)
97
98
 
98
99
  // Emitted when a Moment is destroyed
99
- pub event MomentDestroyed(id: UInt64)
100
+ access(all) event MomentDestroyed(id: UInt64)
100
101
 
101
102
  // Emitted when a Subedition is created
102
- pub event SubeditionCreated(subeditionID: UInt32, name: String, metadata: {String:String})
103
+ access(all) event SubeditionCreated(subeditionID: UInt32, name: String, metadata: {String:String})
103
104
 
104
105
  // Emitted when a Subedition is linked to the specific Moment
105
- pub event SubeditionAddedToMoment(momentID: UInt64, subeditionID: UInt32, setID: UInt32, playID: UInt32)
106
+ access(all) event SubeditionAddedToMoment(momentID: UInt64, subeditionID: UInt32, setID: UInt32, playID: UInt32)
106
107
 
107
108
  // -----------------------------------------------------------------------
108
109
  // TopShot contract-level fields.
@@ -112,7 +113,7 @@ pub contract TopShot: NonFungibleToken {
112
113
  // Series that this Set belongs to.
113
114
  // Series is a concept that indicates a group of Sets through time.
114
115
  // Many Sets can exist at a time, but only one series.
115
- pub var currentSeries: UInt32
116
+ access(all) var currentSeries: UInt32
116
117
 
117
118
  // Variable size dictionary of Play structs
118
119
  access(self) var playDatas: {UInt32: Play}
@@ -126,17 +127,17 @@ pub contract TopShot: NonFungibleToken {
126
127
  // The ID that is used to create Plays.
127
128
  // Every time a Play is created, playID is assigned
128
129
  // to the new Play's ID and then is incremented by 1.
129
- pub var nextPlayID: UInt32
130
+ access(all) var nextPlayID: UInt32
130
131
 
131
132
  // The ID that is used to create Sets. Every time a Set is created
132
133
  // setID is assigned to the new set's ID and then is incremented by 1.
133
- pub var nextSetID: UInt32
134
+ access(all) var nextSetID: UInt32
134
135
 
135
136
  // The total number of Top shot Moment NFTs that have been created
136
137
  // Because NFTs can be destroyed, it doesn't necessarily mean that this
137
138
  // reflects the total number of NFTs in existence, just the number that
138
139
  // have been minted to date. Also used as global moment IDs for minting.
139
- pub var totalSupply: UInt64
140
+ access(all) var totalSupply: UInt64
140
141
 
141
142
  // -----------------------------------------------------------------------
142
143
  // TopShot contract-level Composite Type definitions
@@ -156,16 +157,16 @@ pub contract TopShot: NonFungibleToken {
156
157
  // its metadata. The plays are publicly accessible, so anyone can
157
158
  // read the metadata associated with a specific play ID
158
159
  //
159
- pub struct Play {
160
+ access(all) struct Play {
160
161
 
161
162
  // The unique ID for the Play
162
- pub let playID: UInt32
163
+ access(all) let playID: UInt32
163
164
 
164
165
  // Stores all the metadata about the play as a string mapping
165
166
  // This is not the long term way NFT metadata will be stored. It's a temporary
166
167
  // construct while we figure out a better way to do metadata.
167
168
  //
168
- pub let metadata: {String: String}
169
+ access(all) let metadata: {String: String}
169
170
 
170
171
  init(metadata: {String: String}) {
171
172
  pre {
@@ -196,19 +197,19 @@ pub contract TopShot: NonFungibleToken {
196
197
  // at the end of the contract. Only the admin has the ability
197
198
  // to modify any data in the private Set resource.
198
199
  //
199
- pub struct SetData {
200
+ access(all) struct SetData {
200
201
 
201
202
  // Unique ID for the Set
202
- pub let setID: UInt32
203
+ access(all) let setID: UInt32
203
204
 
204
205
  // Name of the Set
205
206
  // ex. "Times when the Toronto Raptors choked in the playoffs"
206
- pub let name: String
207
+ access(all) let name: String
207
208
 
208
209
  // Series that this Set belongs to.
209
210
  // Series is a concept that indicates a group of Sets through time.
210
211
  // Many Sets can exist at a time, but only one series.
211
- pub let series: UInt32
212
+ access(all) let series: UInt32
212
213
 
213
214
  init(name: String) {
214
215
  pre {
@@ -239,10 +240,10 @@ pub contract TopShot: NonFungibleToken {
239
240
  //
240
241
  // If retireAll() and lock() are called back-to-back,
241
242
  // the Set is closed off forever and nothing more can be done with it.
242
- pub resource Set {
243
+ access(all) resource Set {
243
244
 
244
245
  // Unique ID for the set
245
- pub let setID: UInt32
246
+ access(all) let setID: UInt32
246
247
 
247
248
  // Array of plays that are a part of this set.
248
249
  // When a play is added to the set, its ID gets appended here.
@@ -263,7 +264,7 @@ pub contract TopShot: NonFungibleToken {
263
264
  // If a Set is locked, Plays cannot be added, but
264
265
  // Moments can still be minted from Plays
265
266
  // that exist in the Set.
266
- pub var locked: Bool
267
+ access(all) var locked: Bool
267
268
 
268
269
  // Mapping of Play IDs that indicates the number of Moments
269
270
  // that have been minted for specific Plays in this Set.
@@ -291,7 +292,7 @@ pub contract TopShot: NonFungibleToken {
291
292
  // The Set needs to be not locked
292
293
  // The Play can't have already been added to the Set
293
294
  //
294
- pub fun addPlay(playID: UInt32) {
295
+ access(all) fun addPlay(playID: UInt32) {
295
296
  pre {
296
297
  TopShot.playDatas[playID] != nil: "Cannot add the Play to Set: Play doesn't exist."
297
298
  !self.locked: "Cannot add the play to the Set after the set has been locked."
@@ -315,7 +316,7 @@ pub contract TopShot: NonFungibleToken {
315
316
  // Parameters: playIDs: The IDs of the Plays that are being added
316
317
  // as an array
317
318
  //
318
- pub fun addPlays(playIDs: [UInt32]) {
319
+ access(all) fun addPlays(playIDs: [UInt32]) {
319
320
  for play in playIDs {
320
321
  self.addPlay(playID: play)
321
322
  }
@@ -328,7 +329,7 @@ pub contract TopShot: NonFungibleToken {
328
329
  // Pre-Conditions:
329
330
  // The Play is part of the Set and not retired (available for minting).
330
331
  //
331
- pub fun retirePlay(playID: UInt32) {
332
+ access(all) fun retirePlay(playID: UInt32) {
332
333
  pre {
333
334
  self.retired[playID] != nil: "Cannot retire the Play: Play doesn't exist in this set!"
334
335
  }
@@ -343,7 +344,7 @@ pub contract TopShot: NonFungibleToken {
343
344
  // retireAll retires all the plays in the Set
344
345
  // Afterwards, none of the retired Plays will be able to mint new Moments
345
346
  //
346
- pub fun retireAll() {
347
+ access(all) fun retireAll() {
347
348
  for play in self.plays {
348
349
  self.retirePlay(playID: play)
349
350
  }
@@ -353,7 +354,7 @@ pub contract TopShot: NonFungibleToken {
353
354
  //
354
355
  // Pre-Conditions:
355
356
  // The Set should not be locked
356
- pub fun lock() {
357
+ access(all) fun lock() {
357
358
  if !self.locked {
358
359
  self.locked = true
359
360
  emit SetLocked(setID: self.setID)
@@ -369,7 +370,7 @@ pub contract TopShot: NonFungibleToken {
369
370
  //
370
371
  // Returns: The NFT that was minted
371
372
  //
372
- pub fun mintMoment(playID: UInt32): @NFT {
373
+ access(all) fun mintMoment(playID: UInt32): @NFT {
373
374
  pre {
374
375
  self.retired[playID] != nil: "Cannot mint the moment: This play doesn't exist."
375
376
  !self.retired[playID]!: "Cannot mint the moment from this play: This play has been retired."
@@ -399,7 +400,7 @@ pub contract TopShot: NonFungibleToken {
399
400
  //
400
401
  // Returns: Collection object that contains all the Moments that were minted
401
402
  //
402
- pub fun batchMintMoment(playID: UInt32, quantity: UInt64): @Collection {
403
+ access(all) fun batchMintMoment(playID: UInt32, quantity: UInt64): @Collection {
403
404
  let newCollection <- create Collection()
404
405
 
405
406
  var i: UInt64 = 0
@@ -421,7 +422,7 @@ pub contract TopShot: NonFungibleToken {
421
422
  //
422
423
  // Returns: The NFT that was minted
423
424
  //
424
- pub fun mintMomentWithSubedition(playID: UInt32, subeditionID: UInt32): @NFT {
425
+ access(all) fun mintMomentWithSubedition(playID: UInt32, subeditionID: UInt32): @NFT {
425
426
  pre {
426
427
  self.retired[playID] != nil: "Cannot mint the moment: This play doesn't exist."
427
428
  !self.retired[playID]!: "Cannot mint the moment from this play: This play has been retired."
@@ -429,7 +430,7 @@ pub contract TopShot: NonFungibleToken {
429
430
 
430
431
  // Gets the number of Moments that have been minted for this subedition
431
432
  // to use as this Moment's serial number
432
- let subeditionRef = TopShot.account.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
433
+ let subeditionRef = TopShot.account.storage.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
433
434
  ?? panic("No subedition admin resource in storage")
434
435
 
435
436
  let numInSubedition = subeditionRef.getNumberMintedPerSubedition(setID: self.setID,
@@ -463,7 +464,7 @@ pub contract TopShot: NonFungibleToken {
463
464
  //
464
465
  // Returns: Collection object that contains all the Moments that were minted
465
466
  //
466
- pub fun batchMintMomentWithSubedition(playID: UInt32, quantity: UInt64, subeditionID: UInt32): @Collection {
467
+ access(all) fun batchMintMomentWithSubedition(playID: UInt32, quantity: UInt64, subeditionID: UInt32): @Collection {
467
468
  let newCollection <- create Collection()
468
469
 
469
470
  var i: UInt64 = 0
@@ -476,15 +477,15 @@ pub contract TopShot: NonFungibleToken {
476
477
  return <-newCollection
477
478
  }
478
479
 
479
- pub fun getPlays(): [UInt32] {
480
+ access(all) view fun getPlays(): [UInt32] {
480
481
  return self.plays
481
482
  }
482
483
 
483
- pub fun getRetired(): {UInt32: Bool} {
484
+ access(all) view fun getRetired(): {UInt32: Bool} {
484
485
  return self.retired
485
486
  }
486
487
 
487
- pub fun getNumMintedPerPlay(): {UInt32: UInt32} {
488
+ access(all) view fun getNumMintedPerPlay(): {UInt32: UInt32} {
488
489
  return self.numberMintedPerPlay
489
490
  }
490
491
  }
@@ -494,13 +495,13 @@ pub contract TopShot: NonFungibleToken {
494
495
  // with the desired set ID
495
496
  // let setData = TopShot.QuerySetData(setID: 12)
496
497
  //
497
- pub struct QuerySetData {
498
- pub let setID: UInt32
499
- pub let name: String
500
- pub let series: UInt32
498
+ access(all) struct QuerySetData {
499
+ access(all) let setID: UInt32
500
+ access(all) let name: String
501
+ access(all) let series: UInt32
501
502
  access(self) var plays: [UInt32]
502
503
  access(self) var retired: {UInt32: Bool}
503
- pub var locked: Bool
504
+ access(all) var locked: Bool
504
505
  access(self) var numberMintedPerPlay: {UInt32: UInt32}
505
506
 
506
507
  init(setID: UInt32) {
@@ -514,36 +515,36 @@ pub contract TopShot: NonFungibleToken {
514
515
  self.setID = setID
515
516
  self.name = setData.name
516
517
  self.series = setData.series
517
- self.plays = set.plays
518
- self.retired = set.retired
518
+ self.plays = set.getPlays()
519
+ self.retired = set.getRetired()
519
520
  self.locked = set.locked
520
- self.numberMintedPerPlay = set.numberMintedPerPlay
521
+ self.numberMintedPerPlay = set.getNumMintedPerPlay()
521
522
  }
522
523
 
523
- pub fun getPlays(): [UInt32] {
524
+ access(all) view fun getPlays(): [UInt32] {
524
525
  return self.plays
525
526
  }
526
527
 
527
- pub fun getRetired(): {UInt32: Bool} {
528
+ access(all) view fun getRetired(): {UInt32: Bool} {
528
529
  return self.retired
529
530
  }
530
531
 
531
- pub fun getNumberMintedPerPlay(): {UInt32: UInt32} {
532
+ access(all) view fun getNumberMintedPerPlay(): {UInt32: UInt32} {
532
533
  return self.numberMintedPerPlay
533
534
  }
534
535
  }
535
536
 
536
- pub struct MomentData {
537
+ access(all) struct MomentData {
537
538
 
538
539
  // The ID of the Set that the Moment comes from
539
- pub let setID: UInt32
540
+ access(all) let setID: UInt32
540
541
 
541
542
  // The ID of the Play that the Moment references
542
- pub let playID: UInt32
543
+ access(all) let playID: UInt32
543
544
 
544
545
  // The place in the edition that this Moment was minted
545
546
  // Otherwise know as the serial number
546
- pub let serialNumber: UInt32
547
+ access(all) let serialNumber: UInt32
547
548
 
548
549
  init(setID: UInt32, playID: UInt32, serialNumber: UInt32) {
549
550
  self.setID = setID
@@ -556,38 +557,38 @@ pub contract TopShot: NonFungibleToken {
556
557
  // This is an implementation of a custom metadata view for Top Shot.
557
558
  // This view contains the play metadata.
558
559
  //
559
- pub struct TopShotMomentMetadataView {
560
-
561
- pub let fullName: String?
562
- pub let firstName: String?
563
- pub let lastName: String?
564
- pub let birthdate: String?
565
- pub let birthplace: String?
566
- pub let jerseyNumber: String?
567
- pub let draftTeam: String?
568
- pub let draftYear: String?
569
- pub let draftSelection: String?
570
- pub let draftRound: String?
571
- pub let teamAtMomentNBAID: String?
572
- pub let teamAtMoment: String?
573
- pub let primaryPosition: String?
574
- pub let height: String?
575
- pub let weight: String?
576
- pub let totalYearsExperience: String?
577
- pub let nbaSeason: String?
578
- pub let dateOfMoment: String?
579
- pub let playCategory: String?
580
- pub let playType: String?
581
- pub let homeTeamName: String?
582
- pub let awayTeamName: String?
583
- pub let homeTeamScore: String?
584
- pub let awayTeamScore: String?
585
- pub let seriesNumber: UInt32?
586
- pub let setName: String?
587
- pub let serialNumber: UInt32
588
- pub let playID: UInt32
589
- pub let setID: UInt32
590
- pub let numMomentsInEdition: UInt32?
560
+ access(all) struct TopShotMomentMetadataView {
561
+
562
+ access(all) let fullName: String?
563
+ access(all) let firstName: String?
564
+ access(all) let lastName: String?
565
+ access(all) let birthdate: String?
566
+ access(all) let birthplace: String?
567
+ access(all) let jerseyNumber: String?
568
+ access(all) let draftTeam: String?
569
+ access(all) let draftYear: String?
570
+ access(all) let draftSelection: String?
571
+ access(all) let draftRound: String?
572
+ access(all) let teamAtMomentNBAID: String?
573
+ access(all) let teamAtMoment: String?
574
+ access(all) let primaryPosition: String?
575
+ access(all) let height: String?
576
+ access(all) let weight: String?
577
+ access(all) let totalYearsExperience: String?
578
+ access(all) let nbaSeason: String?
579
+ access(all) let dateOfMoment: String?
580
+ access(all) let playCategory: String?
581
+ access(all) let playType: String?
582
+ access(all) let homeTeamName: String?
583
+ access(all) let awayTeamName: String?
584
+ access(all) let homeTeamScore: String?
585
+ access(all) let awayTeamScore: String?
586
+ access(all) let seriesNumber: UInt32?
587
+ access(all) let setName: String?
588
+ access(all) let serialNumber: UInt32
589
+ access(all) let playID: UInt32
590
+ access(all) let setID: UInt32
591
+ access(all) let numMomentsInEdition: UInt32?
591
592
 
592
593
  init(
593
594
  fullName: String?,
@@ -656,13 +657,13 @@ pub contract TopShot: NonFungibleToken {
656
657
 
657
658
  // The resource that represents the Moment NFTs
658
659
  //
659
- pub resource NFT: NonFungibleToken.INFT, MetadataViews.Resolver {
660
+ access(all) resource NFT: NonFungibleToken.NFT {
660
661
 
661
662
  // Global unique moment ID
662
- pub let id: UInt64
663
+ access(all) let id: UInt64
663
664
 
664
665
  // Struct of Moment metadata
665
- pub let data: MomentData
666
+ access(all) let data: MomentData
666
667
 
667
668
  init(serialNumber: UInt32, playID: UInt32, setID: UInt32, subeditionID: UInt32) {
668
669
  // Increment the global Moment IDs
@@ -681,12 +682,15 @@ pub contract TopShot: NonFungibleToken {
681
682
  }
682
683
 
683
684
  // If the Moment is destroyed, emit an event to indicate
684
- // to outside ovbservers that it has been destroyed
685
- destroy() {
686
- emit MomentDestroyed(id: self.id)
687
- }
688
-
689
- pub fun name(): String {
685
+ // to outside observers that it has been destroyed
686
+ access(all) event ResourceDestroyed(
687
+ id: UInt64 = self.id,
688
+ serialNumber: UInt32 = self.data.serialNumber,
689
+ playID: UInt32 = self.data.playID,
690
+ setID: UInt32 = self.data.setID
691
+ )
692
+
693
+ access(all) view fun name(): String {
690
694
  let fullName: String = TopShot.getPlayMetaDataByField(playID: self.data.playID, field: "FullName") ?? ""
691
695
  let playType: String = TopShot.getPlayMetaDataByField(playID: self.data.playID, field: "PlayType") ?? ""
692
696
  return fullName
@@ -708,14 +712,14 @@ pub contract TopShot: NonFungibleToken {
708
712
 
709
713
  /// The description of the Moment. If Tagline property of the play is empty, compose it using the buildDescString function
710
714
  /// If the Tagline property is not empty, use that as the description
711
- pub fun description(): String {
715
+ access(all) fun description(): String {
712
716
  let playDesc: String = TopShot.getPlayMetaDataByField(playID: self.data.playID, field: "Tagline") ?? ""
713
717
 
714
718
  return playDesc.length > 0 ? playDesc : self.buildDescString()
715
719
  }
716
720
 
717
721
  // All supported metadata views for the Moment including the Core NFT Views
718
- pub fun getViews(): [Type] {
722
+ access(all) view fun getViews(): [Type] {
719
723
  return [
720
724
  Type<MetadataViews.Display>(),
721
725
  Type<TopShotMomentMetadataView>(),
@@ -732,7 +736,7 @@ pub contract TopShot: NonFungibleToken {
732
736
 
733
737
 
734
738
 
735
- pub fun resolveView(_ view: Type): AnyStruct? {
739
+ access(all) fun resolveView(_ view: Type): AnyStruct? {
736
740
  switch view {
737
741
  case Type<MetadataViews.Display>():
738
742
  return MetadataViews.Display(
@@ -787,56 +791,13 @@ pub contract TopShot: NonFungibleToken {
787
791
  UInt64(self.data.serialNumber)
788
792
  )
789
793
  case Type<MetadataViews.Royalties>():
790
- let royaltyReceiver: Capability<&{FungibleToken.Receiver}> =
791
- getAccount(TopShot.RoyaltyAddress()).getCapability<&AnyResource{FungibleToken.Receiver}>(MetadataViews.getRoyaltyReceiverPublicPath())
792
- return MetadataViews.Royalties(
793
- royalties: [
794
- MetadataViews.Royalty(
795
- receiver: royaltyReceiver,
796
- cut: 0.05,
797
- description: "NBATopShot marketplace royalty"
798
- )
799
- ]
800
- )
794
+ return TopShot.resolveContractView(resourceType: nil, viewType: Type<MetadataViews.Royalties>())
801
795
  case Type<MetadataViews.ExternalURL>():
802
796
  return MetadataViews.ExternalURL(self.getMomentURL())
803
797
  case Type<MetadataViews.NFTCollectionData>():
804
- return MetadataViews.NFTCollectionData(
805
- storagePath: /storage/MomentCollection,
806
- publicPath: /public/MomentCollection,
807
- providerPath: /private/MomentCollection,
808
- publicCollection: Type<&TopShot.Collection{TopShot.MomentCollectionPublic}>(),
809
- publicLinkedType: Type<&TopShot.Collection{TopShot.MomentCollectionPublic,NonFungibleToken.Receiver,NonFungibleToken.CollectionPublic,MetadataViews.ResolverCollection}>(),
810
- providerLinkedType: Type<&TopShot.Collection{NonFungibleToken.Provider,TopShot.MomentCollectionPublic,NonFungibleToken.Receiver,NonFungibleToken.CollectionPublic,MetadataViews.ResolverCollection}>(),
811
- createEmptyCollectionFunction: (fun (): @NonFungibleToken.Collection {
812
- return <-TopShot.createEmptyCollection()
813
- })
814
- )
798
+ return TopShot.resolveContractView(resourceType: nil, viewType: Type<MetadataViews.NFTCollectionData>())
815
799
  case Type<MetadataViews.NFTCollectionDisplay>():
816
- let bannerImage = MetadataViews.Media(
817
- file: MetadataViews.HTTPFile(
818
- url: "https://nbatopshot.com/static/img/top-shot-logo-horizontal-white.svg"
819
- ),
820
- mediaType: "image/svg+xml"
821
- )
822
- let squareImage = MetadataViews.Media(
823
- file: MetadataViews.HTTPFile(
824
- url: "https://nbatopshot.com/static/img/og/og.png"
825
- ),
826
- mediaType: "image/png"
827
- )
828
- return MetadataViews.NFTCollectionDisplay(
829
- name: "NBA-Top-Shot",
830
- description: "NBA Top Shot is your chance to own, sell, and trade official digital collectibles of the NBA and WNBA's greatest plays and players",
831
- externalURL: MetadataViews.ExternalURL("https://nbatopshot.com"),
832
- squareImage: squareImage,
833
- bannerImage: bannerImage,
834
- socials: {
835
- "twitter": MetadataViews.ExternalURL("https://twitter.com/nbatopshot"),
836
- "discord": MetadataViews.ExternalURL("https://discord.com/invite/nbatopshot"),
837
- "instagram": MetadataViews.ExternalURL("https://www.instagram.com/nbatopshot")
838
- }
839
- )
800
+ return TopShot.resolveContractView(resourceType: nil, viewType: Type<MetadataViews.NFTCollectionDisplay>())
840
801
  case Type<MetadataViews.Traits>():
841
802
  // sports radar team id
842
803
  let excludedNames: [String] = ["TeamAtMomentNBAID"]
@@ -844,14 +805,15 @@ pub contract TopShot: NonFungibleToken {
844
805
  let traitDictionary: {String: AnyStruct} = {
845
806
  "SeriesNumber": TopShot.getSetSeries(setID: self.data.setID),
846
807
  "SetName": TopShot.getSetName(setID: self.data.setID),
847
- "SerialNumber": self.data.serialNumber
808
+ "SerialNumber": self.data.serialNumber,
809
+ "Locked": TopShotLocking.isLocked(nftRef: &self as &{NonFungibleToken.NFT})
848
810
  }
849
811
  // add play specific data
850
812
  let fullDictionary = self.mapPlayData(dict: traitDictionary)
851
813
  return MetadataViews.dictToTraits(dict: fullDictionary, excludedNames: excludedNames)
852
814
  case Type<MetadataViews.Medias>():
853
815
  return MetadataViews.Medias(
854
- items: [
816
+ [
855
817
  MetadataViews.Media(
856
818
  file: MetadataViews.HTTPFile(
857
819
  url: self.mediumimage()
@@ -875,7 +837,7 @@ pub contract TopShot: NonFungibleToken {
875
837
 
876
838
  // mapPlayData helps build our trait map from play metadata
877
839
  // Returns: The trait map with all non-empty fields from play data added
878
- pub fun mapPlayData(dict: {String: AnyStruct}) : {String: AnyStruct} {
840
+ access(all) fun mapPlayData(dict: {String: AnyStruct}) : {String: AnyStruct} {
879
841
  let playMetadata = TopShot.getPlayMetaData(playID: self.data.playID) ?? {}
880
842
  for name in playMetadata.keys {
881
843
  let value = playMetadata[name] ?? ""
@@ -888,53 +850,58 @@ pub contract TopShot: NonFungibleToken {
888
850
 
889
851
  // getMomentURL
890
852
  // Returns: The computed external url of the moment
891
- pub fun getMomentURL(): String {
853
+ access(all) view fun getMomentURL(): String {
892
854
  return "https://nbatopshot.com/moment/".concat(self.id.toString())
893
855
  }
894
856
  // getEditionName Moment's edition name is a combination of the Moment's setName and playID
895
857
  // `setName: #playID`
896
- pub fun getEditionName() : String {
858
+ access(all) view fun getEditionName() : String {
897
859
  let setName: String = TopShot.getSetName(setID: self.data.setID) ?? ""
898
860
  let editionName = setName.concat(": #").concat(self.data.playID.toString())
899
861
  return editionName
900
862
  }
901
863
 
902
- pub fun assetPath(): String {
864
+ access(all) view fun assetPath(): String {
903
865
  return "https://assets.nbatopshot.com/media/".concat(self.id.toString())
904
866
  }
905
867
 
906
868
  // returns a url to display an medium sized image
907
- pub fun mediumimage(): String {
869
+ access(all) fun mediumimage(): String {
908
870
  let url = self.assetPath().concat("?width=512")
909
871
  return self.appendOptionalParams(url: url, firstDelim: "&")
910
872
  }
911
873
 
912
874
  // a url to display a thumbnail associated with the moment
913
- pub fun thumbnail(): String {
875
+ access(all) fun thumbnail(): String {
914
876
  let url = self.assetPath().concat("?width=256")
915
877
  return self.appendOptionalParams(url: url, firstDelim: "&")
916
878
  }
917
879
 
918
880
  // a url to display a video associated with the moment
919
- pub fun video(): String {
881
+ access(all) fun video(): String {
920
882
  let url = self.assetPath().concat("/video")
921
883
  return self.appendOptionalParams(url: url, firstDelim: "?")
922
884
  }
923
885
 
924
886
  // appends and optional network param needed to resolve the media
925
- pub fun appendOptionalParams(url: String, firstDelim: String): String {
887
+ access(all) fun appendOptionalParams(url: String, firstDelim: String): String {
926
888
  if (TopShot.Network() == "testnet") {
927
889
  return url.concat(firstDelim).concat("testnet")
928
890
  }
929
891
  return url
930
892
  }
893
+
894
+ // Create an empty Collection for Pinnacle NFTs and return it to the caller
895
+ access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
896
+ return <- TopShot.createEmptyCollection(nftType: Type<@TopShot.NFT>())
897
+ }
931
898
  }
932
899
 
933
900
  // Admin is a special authorization resource that
934
901
  // allows the owner to perform important functions to modify the
935
902
  // various aspects of the Plays, Sets, and Moments
936
903
  //
937
- pub resource Admin {
904
+ access(all) resource Admin {
938
905
 
939
906
  // createPlay creates a new Play struct
940
907
  // and stores it in the Plays dictionary in the TopShot smart contract
@@ -945,7 +912,7 @@ pub contract TopShot: NonFungibleToken {
945
912
  //
946
913
  // Returns: the ID of the new Play object
947
914
  //
948
- pub fun createPlay(metadata: {String: String}): UInt32 {
915
+ access(all) fun createPlay(metadata: {String: String}): UInt32 {
949
916
  // Create the new Play
950
917
  var newPlay = Play(metadata: metadata)
951
918
  let newID = newPlay.playID
@@ -965,7 +932,7 @@ pub contract TopShot: NonFungibleToken {
965
932
  /// Parameters: playID: The ID of the play to update
966
933
  /// tagline: A string to be used as the tagline for the play
967
934
  /// Returns: The ID of the play
968
- pub fun updatePlayTagline(playID: UInt32, tagline: String): UInt32 {
935
+ access(all) fun updatePlayTagline(playID: UInt32, tagline: String): UInt32 {
969
936
  let tmpPlay = TopShot.playDatas[playID] ?? panic("playID does not exist")
970
937
  tmpPlay.updateTagline(tagline: tagline)
971
938
  return playID
@@ -977,7 +944,7 @@ pub contract TopShot: NonFungibleToken {
977
944
  // Parameters: name: The name of the Set
978
945
  //
979
946
  // Returns: The ID of the created set
980
- pub fun createSet(name: String): UInt32 {
947
+ access(all) fun createSet(name: String): UInt32 {
981
948
 
982
949
  // Create the new Set
983
950
  var newSet <- create Set(name: name)
@@ -1004,7 +971,7 @@ pub contract TopShot: NonFungibleToken {
1004
971
  // Returns: A reference to the Set with all of the fields
1005
972
  // and methods exposed
1006
973
  //
1007
- pub fun borrowSet(setID: UInt32): &Set {
974
+ access(all) view fun borrowSet(setID: UInt32): &Set {
1008
975
  pre {
1009
976
  TopShot.sets[setID] != nil: "Cannot borrow Set: The Set doesn't exist"
1010
977
  }
@@ -1020,7 +987,7 @@ pub contract TopShot: NonFungibleToken {
1020
987
  //
1021
988
  // Returns: The new series number
1022
989
  //
1023
- pub fun startNewSeries(): UInt32 {
990
+ access(all) fun startNewSeries(): UInt32 {
1024
991
  // End the current series and start a new one
1025
992
  // by incrementing the TopShot series number
1026
993
  TopShot.currentSeries = TopShot.currentSeries + UInt32(1)
@@ -1032,8 +999,8 @@ pub contract TopShot: NonFungibleToken {
1032
999
 
1033
1000
  // createSubeditionResource creates new SubeditionMap resource that
1034
1001
  // will be used to mint Moments with Subeditions
1035
- pub fun createSubeditionAdminResource() {
1036
- TopShot.account.save<@SubeditionAdmin>(<- create SubeditionAdmin(), to: TopShot.SubeditionAdminStoragePath())
1002
+ access(all) fun createSubeditionAdminResource() {
1003
+ TopShot.account.storage.save<@SubeditionAdmin>(<- create SubeditionAdmin(), to: TopShot.SubeditionAdminStoragePath())
1037
1004
  }
1038
1005
 
1039
1006
  // setMomentsSubedition saves which Subedition the Moment belongs to
@@ -1043,8 +1010,8 @@ pub contract TopShot: NonFungibleToken {
1043
1010
  // setID: The ID of the Set that the Moment references
1044
1011
  // playID: The ID of the Play that the Moment references
1045
1012
  //
1046
- pub fun setMomentsSubedition(nftID: UInt64, subeditionID: UInt32, setID: UInt32, playID: UInt32) {
1047
- let subeditionAdmin = TopShot.account.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1013
+ access(all) fun setMomentsSubedition(nftID: UInt64, subeditionID: UInt32, setID: UInt32, playID: UInt32) {
1014
+ let subeditionAdmin = TopShot.account.storage.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1048
1015
  ?? panic("No subedition admin resource in storage")
1049
1016
 
1050
1017
  subeditionAdmin.setMomentsSubedition(nftID: nftID, subeditionID: subeditionID, setID: setID, playID: playID)
@@ -1058,8 +1025,8 @@ pub contract TopShot: NonFungibleToken {
1058
1025
  //
1059
1026
  // Returns: the ID of the new Subedition object
1060
1027
  //
1061
- pub fun createSubedition(name:String, metadata:{String:String}): UInt32 {
1062
- let subeditionAdmin = TopShot.account.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1028
+ access(all) fun createSubedition(name:String, metadata:{String:String}): UInt32 {
1029
+ let subeditionAdmin = TopShot.account.storage.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1063
1030
  ?? panic("No subedition admin resource in storage")
1064
1031
 
1065
1032
  return subeditionAdmin.createSubedition(name:name, metadata:metadata)
@@ -1067,7 +1034,7 @@ pub contract TopShot: NonFungibleToken {
1067
1034
 
1068
1035
  // createNewAdmin creates a new Admin resource
1069
1036
  //
1070
- pub fun createNewAdmin(): @Admin {
1037
+ access(all) fun createNewAdmin(): @Admin {
1071
1038
  return <-create Admin()
1072
1039
  }
1073
1040
  }
@@ -1075,12 +1042,9 @@ pub contract TopShot: NonFungibleToken {
1075
1042
  // This is the interface that users can cast their Moment Collection as
1076
1043
  // to allow others to deposit Moments into their Collection. It also allows for reading
1077
1044
  // the IDs of Moments in the Collection.
1078
- pub resource interface MomentCollectionPublic {
1079
- pub fun deposit(token: @NonFungibleToken.NFT)
1080
- pub fun batchDeposit(tokens: @NonFungibleToken.Collection)
1081
- pub fun getIDs(): [UInt64]
1082
- pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT
1083
- pub fun borrowMoment(id: UInt64): &TopShot.NFT? {
1045
+ access(all) resource interface MomentCollectionPublic : NonFungibleToken.CollectionPublic {
1046
+ access(all) fun batchDeposit(tokens: @{NonFungibleToken.Collection})
1047
+ access(all) fun borrowMoment(id: UInt64): &TopShot.NFT? {
1084
1048
  // If the result isn't nil, the id of the returned reference
1085
1049
  // should be the same as the argument to the function
1086
1050
  post {
@@ -1093,35 +1057,62 @@ pub contract TopShot: NonFungibleToken {
1093
1057
  // Collection is a resource that every user who owns NFTs
1094
1058
  // will store in their account to manage their NFTS
1095
1059
  //
1096
- pub resource Collection: MomentCollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic, MetadataViews.ResolverCollection {
1060
+ access(all) resource Collection: MomentCollectionPublic, NonFungibleToken.Collection {
1097
1061
  // Dictionary of Moment conforming tokens
1098
1062
  // NFT is a resource type with a UInt64 ID field
1099
- pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT}
1063
+ access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
1100
1064
 
1101
1065
  init() {
1102
1066
  self.ownedNFTs <- {}
1103
1067
  }
1104
1068
 
1069
+ // Return a list of NFT types that this receiver accepts
1070
+ access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
1071
+ let supportedTypes: {Type: Bool} = {}
1072
+ supportedTypes[Type<@TopShot.NFT>()] = true
1073
+ return supportedTypes
1074
+ }
1075
+
1076
+ // Return whether or not the given type is accepted by the collection
1077
+ // A collection that can accept any type should just return true by default
1078
+ access(all) view fun isSupportedNFTType(type: Type): Bool {
1079
+ if type == Type<@TopShot.NFT>() {
1080
+ return true
1081
+ }
1082
+ return false
1083
+ }
1084
+
1085
+ // Return the amount of NFTs stored in the collection
1086
+ access(all) view fun getLength(): Int {
1087
+ return self.ownedNFTs.keys.length
1088
+ }
1089
+
1090
+ // Create an empty Collection for TopShot NFTs and return it to the caller
1091
+ access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
1092
+ return <- TopShot.createEmptyCollection(nftType: Type<@TopShot.NFT>())
1093
+ }
1094
+
1105
1095
  // withdraw removes an Moment from the Collection and moves it to the caller
1106
1096
  //
1107
1097
  // Parameters: withdrawID: The ID of the NFT
1108
1098
  // that is to be removed from the Collection
1109
1099
  //
1110
1100
  // returns: @NonFungibleToken.NFT the token that was withdrawn
1111
- pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT {
1101
+ access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
1112
1102
 
1113
1103
  // Borrow nft and check if locked
1114
- let nft = self.borrowNFT(id: withdrawID)
1104
+ let nft = self.borrowNFT(withdrawID)
1105
+ ?? panic("Cannot borrow: empty reference")
1115
1106
  if TopShotLocking.isLocked(nftRef: nft) {
1116
1107
  panic("Cannot withdraw: Moment is locked")
1117
1108
  }
1118
1109
 
1119
1110
  // Remove the nft from the Collection
1120
- let token <- self.ownedNFTs.remove(key: withdrawID)
1111
+ let token <- self.ownedNFTs.remove(key: withdrawID)
1121
1112
  ?? panic("Cannot withdraw: Moment does not exist in the collection")
1122
1113
 
1123
1114
  emit Withdraw(id: token.id, from: self.owner?.address)
1124
-
1115
+
1125
1116
  // Return the withdrawn token
1126
1117
  return <-token
1127
1118
  }
@@ -1133,7 +1124,7 @@ pub contract TopShot: NonFungibleToken {
1133
1124
  // Returns: @NonFungibleToken.Collection: A collection that contains
1134
1125
  // the withdrawn moments
1135
1126
  //
1136
- pub fun batchWithdraw(ids: [UInt64]): @NonFungibleToken.Collection {
1127
+ access(NonFungibleToken.Withdraw) fun batchWithdraw(ids: [UInt64]): @{NonFungibleToken.Collection} {
1137
1128
  // Create a new empty Collection
1138
1129
  var batchCollection <- create Collection()
1139
1130
 
@@ -1150,7 +1141,7 @@ pub contract TopShot: NonFungibleToken {
1150
1141
  //
1151
1142
  // Paramters: token: the NFT to be deposited in the collection
1152
1143
  //
1153
- pub fun deposit(token: @NonFungibleToken.NFT) {
1144
+ access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
1154
1145
 
1155
1146
  // Cast the deposited token as a TopShot NFT to make sure
1156
1147
  // it is the correct type
@@ -1174,7 +1165,7 @@ pub contract TopShot: NonFungibleToken {
1174
1165
 
1175
1166
  // batchDeposit takes a Collection object as an argument
1176
1167
  // and deposits each contained NFT into this Collection
1177
- pub fun batchDeposit(tokens: @NonFungibleToken.Collection) {
1168
+ access(all) fun batchDeposit(tokens: @{NonFungibleToken.Collection}) {
1178
1169
 
1179
1170
  // Get an array of the IDs to be deposited
1180
1171
  let keys = tokens.getIDs()
@@ -1190,7 +1181,7 @@ pub contract TopShot: NonFungibleToken {
1190
1181
 
1191
1182
  // lock takes a token id and a duration in seconds and locks
1192
1183
  // the moment for that duration
1193
- pub fun lock(id: UInt64, duration: UFix64) {
1184
+ access(NonFungibleToken.Update) fun lock(id: UInt64, duration: UFix64) {
1194
1185
  // Remove the nft from the Collection
1195
1186
  let token <- self.ownedNFTs.remove(key: id)
1196
1187
  ?? panic("Cannot lock: Moment does not exist in the collection")
@@ -1204,7 +1195,7 @@ pub contract TopShot: NonFungibleToken {
1204
1195
 
1205
1196
  // batchLock takes an array of token ids and a duration in seconds
1206
1197
  // it iterates through the ids and locks each for the specified duration
1207
- pub fun batchLock(ids: [UInt64], duration: UFix64) {
1198
+ access(NonFungibleToken.Update) fun batchLock(ids: [UInt64], duration: UFix64) {
1208
1199
  // Iterate through the ids and lock them
1209
1200
  for id in ids {
1210
1201
  self.lock(id: id, duration: duration)
@@ -1213,7 +1204,7 @@ pub contract TopShot: NonFungibleToken {
1213
1204
 
1214
1205
  // unlock takes a token id and attempts to unlock it
1215
1206
  // TopShotLocking.unlockNFT contains business logic around unlock eligibility
1216
- pub fun unlock(id: UInt64) {
1207
+ access(NonFungibleToken.Update) fun unlock(id: UInt64) {
1217
1208
  // Remove the nft from the Collection
1218
1209
  let token <- self.ownedNFTs.remove(key: id)
1219
1210
  ?? panic("Cannot lock: Moment does not exist in the collection")
@@ -1227,15 +1218,40 @@ pub contract TopShot: NonFungibleToken {
1227
1218
 
1228
1219
  // batchUnlock takes an array of token ids
1229
1220
  // it iterates through the ids and unlocks each if they are eligible
1230
- pub fun batchUnlock(ids: [UInt64]) {
1221
+ access(NonFungibleToken.Update) fun batchUnlock(ids: [UInt64]) {
1231
1222
  // Iterate through the ids and unlocks them
1232
1223
  for id in ids {
1233
1224
  self.unlock(id: id)
1234
1225
  }
1235
1226
  }
1236
1227
 
1228
+ // destroyMoments destroys moments in this collection
1229
+ // unlocks the moments if they are locked
1230
+ //
1231
+ // Parameters: ids: An array of NFT IDs
1232
+ // to be destroyed from the Collection
1233
+ access(NonFungibleToken.Update) fun destroyMoments(ids: [UInt64]) {
1234
+ let topShotLockingAdmin = TopShot.account.storage.borrow<&TopShotLocking.Admin>(from: TopShotLocking.AdminStoragePath())
1235
+ ?? panic("No TopShotLocking admin resource in storage")
1236
+
1237
+ for id in ids {
1238
+ // Remove the nft from the Collection
1239
+ let token <- self.ownedNFTs.remove(key: id)
1240
+ ?? panic("Cannot destroy: Moment does not exist in collection: ".concat(id.toString()))
1241
+
1242
+ // Emit a withdraw event here so that platforms do not have to understand TopShot-specific events to see ownership change
1243
+ // A withdraw without a corresponding deposit means the NFT in question has no owner address
1244
+ emit Withdraw(id: id, from: self.owner?.address)
1245
+
1246
+ // does nothing if the moment is not locked
1247
+ topShotLockingAdmin.unlockByID(id: id)
1248
+
1249
+ destroy token
1250
+ }
1251
+ }
1252
+
1237
1253
  // getIDs returns an array of the IDs that are in the Collection
1238
- pub fun getIDs(): [UInt64] {
1254
+ access(all) view fun getIDs(): [UInt64] {
1239
1255
  return self.ownedNFTs.keys
1240
1256
  }
1241
1257
 
@@ -1250,21 +1266,8 @@ pub contract TopShot: NonFungibleToken {
1250
1266
  // not any topshot specific data. Please use borrowMoment to
1251
1267
  // read Moment data.
1252
1268
  //
1253
- pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT {
1254
- return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)!
1255
- }
1256
-
1257
- // Safe way to borrow a reference to an NFT that does not panic
1258
- // Also now part of the NonFungibleToken.PublicCollection interface
1259
- //
1260
- // Parameters: id: The ID of the NFT to get the reference for
1261
- //
1262
- // Returns: An optional reference to the desired NFT, will be nil if the passed ID does not exist
1263
- pub fun borrowNFTSafe(id: UInt64): &NonFungibleToken.NFT? {
1264
- if let nftRef = &self.ownedNFTs[id] as &NonFungibleToken.NFT? {
1265
- return nftRef
1266
- }
1267
- return nil
1269
+ access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
1270
+ return &self.ownedNFTs[id]
1268
1271
  }
1269
1272
 
1270
1273
  // borrowMoment returns a borrowed reference to a Moment
@@ -1277,29 +1280,17 @@ pub contract TopShot: NonFungibleToken {
1277
1280
  // Parameters: id: The ID of the NFT to get the reference for
1278
1281
  //
1279
1282
  // Returns: A reference to the NFT
1280
- pub fun borrowMoment(id: UInt64): &TopShot.NFT? {
1281
- if self.ownedNFTs[id] != nil {
1282
- let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
1283
- return ref as! &TopShot.NFT
1284
- } else {
1285
- return nil
1286
- }
1283
+ access(all) view fun borrowMoment(id: UInt64): &TopShot.NFT? {
1284
+ return self.borrowNFT(id) as! &TopShot.NFT?
1287
1285
  }
1288
1286
 
1289
- pub fun borrowViewResolver(id: UInt64): &AnyResource{MetadataViews.Resolver} {
1290
- let nft = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
1291
- let topShotNFT = nft as! &TopShot.NFT
1292
- return topShotNFT as &AnyResource{MetadataViews.Resolver}
1287
+ access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
1288
+ if let nft = &self.ownedNFTs[id] as &{NonFungibleToken.NFT}? {
1289
+ return nft as &{ViewResolver.Resolver}
1290
+ }
1291
+ return nil
1293
1292
  }
1294
1293
 
1295
- // If a transaction destroys the Collection object,
1296
- // All the NFTs contained within are also destroyed!
1297
- // Much like when Damian Lillard destroys the hopes and
1298
- // dreams of the entire city of Houston.
1299
- //
1300
- destroy() {
1301
- destroy self.ownedNFTs
1302
- }
1303
1294
  }
1304
1295
 
1305
1296
  // -----------------------------------------------------------------------
@@ -1311,14 +1302,17 @@ pub contract TopShot: NonFungibleToken {
1311
1302
  // Once they have a Collection in their storage, they are able to receive
1312
1303
  // Moments in transactions.
1313
1304
  //
1314
- pub fun createEmptyCollection(): @NonFungibleToken.Collection {
1305
+ access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
1306
+ if nftType != Type<@TopShot.NFT>() {
1307
+ panic("NFT type is not supported")
1308
+ }
1315
1309
  return <-create TopShot.Collection()
1316
1310
  }
1317
1311
 
1318
1312
  // getAllPlays returns all the plays in topshot
1319
1313
  //
1320
1314
  // Returns: An array of all the plays that have been created
1321
- pub fun getAllPlays(): [TopShot.Play] {
1315
+ access(all) view fun getAllPlays(): [TopShot.Play] {
1322
1316
  return TopShot.playDatas.values
1323
1317
  }
1324
1318
 
@@ -1327,7 +1321,7 @@ pub contract TopShot: NonFungibleToken {
1327
1321
  // Parameters: playID: The id of the Play that is being searched
1328
1322
  //
1329
1323
  // Returns: The metadata as a String to String mapping optional
1330
- pub fun getPlayMetaData(playID: UInt32): {String: String}? {
1324
+ access(all) view fun getPlayMetaData(playID: UInt32): {String: String}? {
1331
1325
  return self.playDatas[playID]?.metadata
1332
1326
  }
1333
1327
 
@@ -1340,7 +1334,7 @@ pub contract TopShot: NonFungibleToken {
1340
1334
  // field: The field to search for
1341
1335
  //
1342
1336
  // Returns: The metadata field as a String Optional
1343
- pub fun getPlayMetaDataByField(playID: UInt32, field: String): String? {
1337
+ access(all) view fun getPlayMetaDataByField(playID: UInt32, field: String): String? {
1344
1338
  // Don't force a revert if the playID or field is invalid
1345
1339
  if let play = TopShot.playDatas[playID] {
1346
1340
  return play.metadata[field]
@@ -1355,7 +1349,7 @@ pub contract TopShot: NonFungibleToken {
1355
1349
  // Parameters: setID: The id of the Set that is being searched
1356
1350
  //
1357
1351
  // Returns: The QuerySetData struct that has all the important information about the set
1358
- pub fun getSetData(setID: UInt32): QuerySetData? {
1352
+ access(all) fun getSetData(setID: UInt32): QuerySetData? {
1359
1353
  if TopShot.sets[setID] == nil {
1360
1354
  return nil
1361
1355
  } else {
@@ -1369,7 +1363,7 @@ pub contract TopShot: NonFungibleToken {
1369
1363
  // Parameters: setID: The id of the Set that is being searched
1370
1364
  //
1371
1365
  // Returns: The name of the Set
1372
- pub fun getSetName(setID: UInt32): String? {
1366
+ access(all) view fun getSetName(setID: UInt32): String? {
1373
1367
  // Don't force a revert if the setID is invalid
1374
1368
  return TopShot.setDatas[setID]?.name
1375
1369
  }
@@ -1380,7 +1374,7 @@ pub contract TopShot: NonFungibleToken {
1380
1374
  // Parameters: setID: The id of the Set that is being searched
1381
1375
  //
1382
1376
  // Returns: The series that the Set belongs to
1383
- pub fun getSetSeries(setID: UInt32): UInt32? {
1377
+ access(all) view fun getSetSeries(setID: UInt32): UInt32? {
1384
1378
  // Don't force a revert if the setID is invalid
1385
1379
  return TopShot.setDatas[setID]?.series
1386
1380
  }
@@ -1391,7 +1385,7 @@ pub contract TopShot: NonFungibleToken {
1391
1385
  // Parameters: setName: The name of the Set that is being searched
1392
1386
  //
1393
1387
  // Returns: An array of the IDs of the Set if it exists, or nil if doesn't
1394
- pub fun getSetIDsByName(setName: String): [UInt32]? {
1388
+ access(all) fun getSetIDsByName(setName: String): [UInt32]? {
1395
1389
  var setIDs: [UInt32] = []
1396
1390
 
1397
1391
  // Iterate through all the setDatas and search for the name
@@ -1416,7 +1410,7 @@ pub contract TopShot: NonFungibleToken {
1416
1410
  // Parameters: setID: The id of the Set that is being searched
1417
1411
  //
1418
1412
  // Returns: An array of Play IDs
1419
- pub fun getPlaysInSet(setID: UInt32): [UInt32]? {
1413
+ access(all) view fun getPlaysInSet(setID: UInt32): [UInt32]? {
1420
1414
  // Don't force a revert if the setID is invalid
1421
1415
  return TopShot.sets[setID]?.plays
1422
1416
  }
@@ -1430,7 +1424,7 @@ pub contract TopShot: NonFungibleToken {
1430
1424
  // playID: The id of the Play that is being searched
1431
1425
  //
1432
1426
  // Returns: Boolean indicating if the edition is retired or not
1433
- pub fun isEditionRetired(setID: UInt32, playID: UInt32): Bool? {
1427
+ access(all) fun isEditionRetired(setID: UInt32, playID: UInt32): Bool? {
1434
1428
 
1435
1429
  if let setdata = self.getSetData(setID: setID) {
1436
1430
 
@@ -1454,7 +1448,7 @@ pub contract TopShot: NonFungibleToken {
1454
1448
  // Parameters: setID: The id of the Set that is being searched
1455
1449
  //
1456
1450
  // Returns: Boolean indicating if the Set is locked or not
1457
- pub fun isSetLocked(setID: UInt32): Bool? {
1451
+ access(all) view fun isSetLocked(setID: UInt32): Bool? {
1458
1452
  // Don't force a revert if the setID is invalid
1459
1453
  return TopShot.sets[setID]?.locked
1460
1454
  }
@@ -1467,7 +1461,7 @@ pub contract TopShot: NonFungibleToken {
1467
1461
  //
1468
1462
  // Returns: The total number of Moments
1469
1463
  // that have been minted from an edition
1470
- pub fun getNumMomentsInEdition(setID: UInt32, playID: UInt32): UInt32? {
1464
+ access(all) fun getNumMomentsInEdition(setID: UInt32, playID: UInt32): UInt32? {
1471
1465
  if let setdata = self.getSetData(setID: setID) {
1472
1466
 
1473
1467
  // Read the numMintedPerPlay
@@ -1486,8 +1480,8 @@ pub contract TopShot: NonFungibleToken {
1486
1480
  //
1487
1481
  // returns: UInt32? Subedition's ID if exists
1488
1482
  //
1489
- pub fun getMomentsSubedition(nftID: UInt64):UInt32? {
1490
- let subeditionAdmin = self.account.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1483
+ access(all) view fun getMomentsSubedition(nftID: UInt64):UInt32? {
1484
+ let subeditionAdmin = self.account.storage.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1491
1485
  ?? panic("No subedition admin resource in storage")
1492
1486
 
1493
1487
  return subeditionAdmin.getMomentsSubedition(nftID: nftID)
@@ -1496,8 +1490,8 @@ pub contract TopShot: NonFungibleToken {
1496
1490
  // getAllSubeditions returns all the subeditions in topshot subeditionAdmin resource
1497
1491
  //
1498
1492
  // Returns: An array of all the subeditions that have been created
1499
- pub fun getAllSubeditions():[TopShot.Subedition] {
1500
- let subeditionAdmin = self.account.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1493
+ access(all) view fun getAllSubeditions(): &[TopShot.Subedition] {
1494
+ let subeditionAdmin = self.account.storage.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1501
1495
  ?? panic("No subedition admin resource in storage")
1502
1496
  return subeditionAdmin.subeditionDatas.values
1503
1497
  }
@@ -1507,8 +1501,8 @@ pub contract TopShot: NonFungibleToken {
1507
1501
  // Parameters: subeditionID: The id of the Subedition that is being searched
1508
1502
  //
1509
1503
  // Returns: The Subedition struct
1510
- pub fun getSubeditionByID(subeditionID: UInt32):TopShot.Subedition {
1511
- let subeditionAdmin = self.account.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1504
+ access(all) view fun getSubeditionByID(subeditionID: UInt32): &TopShot.Subedition {
1505
+ let subeditionAdmin = self.account.storage.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1512
1506
  ?? panic("No subedition admin resource in storage")
1513
1507
  return subeditionAdmin.subeditionDatas[subeditionID]!
1514
1508
  }
@@ -1518,19 +1512,19 @@ pub contract TopShot: NonFungibleToken {
1518
1512
  //
1519
1513
  // Returns: UInt32
1520
1514
  // the next number in nextSubeditionID from the SubeditionAdmin resource
1521
- pub fun getNextSubeditionID():UInt32 {
1522
- let subeditionAdmin = self.account.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1515
+ access(all) view fun getNextSubeditionID():UInt32 {
1516
+ let subeditionAdmin = self.account.storage.borrow<&SubeditionAdmin>(from: TopShot.SubeditionAdminStoragePath())
1523
1517
  ?? panic("No subedition admin resource in storage")
1524
1518
  return subeditionAdmin.nextSubeditionID
1525
1519
  }
1526
1520
  // SubeditionAdmin is a resource that allows Set to mint Moments with Subeditions
1527
1521
  //
1528
- pub struct Subedition {
1529
- pub let subeditionID: UInt32
1522
+ access(all) struct Subedition {
1523
+ access(all) let subeditionID: UInt32
1530
1524
 
1531
- pub let name: String
1525
+ access(all) let name: String
1532
1526
 
1533
- pub let metadata: {String: String}
1527
+ access(all) let metadata: {String: String}
1534
1528
 
1535
1529
  init(subeditionID: UInt32, name: String, metadata: {String: String}) {
1536
1530
  pre {
@@ -1542,7 +1536,7 @@ pub contract TopShot: NonFungibleToken {
1542
1536
  }
1543
1537
  }
1544
1538
 
1545
- pub resource SubeditionAdmin {
1539
+ access(all) resource SubeditionAdmin {
1546
1540
 
1547
1541
  // Map of number of already minted Moments using Subedition.
1548
1542
  // When a new Moment with Subedition is minted, 1 is added to the
@@ -1570,7 +1564,7 @@ pub contract TopShot: NonFungibleToken {
1570
1564
  //
1571
1565
  // Returns: the ID of the new Subedition object
1572
1566
  //
1573
- pub fun createSubedition(name:String, metadata:{String:String}): UInt32 {
1567
+ access(all) fun createSubedition(name:String, metadata:{String:String}): UInt32 {
1574
1568
 
1575
1569
  let newID = self.nextSubeditionID
1576
1570
 
@@ -1591,7 +1585,7 @@ pub contract TopShot: NonFungibleToken {
1591
1585
  //
1592
1586
  // returns: UInt32? Subedition's ID if exists
1593
1587
  //
1594
- pub fun getMomentsSubedition(nftID: UInt64):UInt32? {
1588
+ access(all) view fun getMomentsSubedition(nftID: UInt64):UInt32? {
1595
1589
  return self.momentsSubedition[nftID]
1596
1590
  }
1597
1591
 
@@ -1605,7 +1599,7 @@ pub contract TopShot: NonFungibleToken {
1605
1599
  //
1606
1600
  // returns: UInt32 Number of Moments, already minted for this Subedition
1607
1601
  //
1608
- pub fun getNumberMintedPerSubedition(setID: UInt32, playID: UInt32, subeditionID: UInt32): UInt32 {
1602
+ access(all) fun getNumberMintedPerSubedition(setID: UInt32, playID: UInt32, subeditionID: UInt32): UInt32 {
1609
1603
  let setPlaySubedition = setID.toString().concat(playID.toString()).concat(subeditionID.toString())
1610
1604
  if !self.numberMintedPerSubedition.containsKey(setPlaySubedition) {
1611
1605
  self.numberMintedPerSubedition.insert(key: setPlaySubedition,UInt32(0))
@@ -1622,7 +1616,7 @@ pub contract TopShot: NonFungibleToken {
1622
1616
  // subeditionID: The ID of the Subedition using which moment will be minted
1623
1617
  //
1624
1618
  //
1625
- pub fun addToNumberMintedPerSubedition(setID: UInt32, playID: UInt32, subeditionID: UInt32) {
1619
+ access(all) fun addToNumberMintedPerSubedition(setID: UInt32, playID: UInt32, subeditionID: UInt32) {
1626
1620
  let setPlaySubedition = setID.toString().concat(playID.toString()).concat(subeditionID.toString())
1627
1621
 
1628
1622
  if !self.numberMintedPerSubedition.containsKey(setPlaySubedition) {
@@ -1639,7 +1633,7 @@ pub contract TopShot: NonFungibleToken {
1639
1633
  // setID: The ID of the Set that the Moment references
1640
1634
  // playID: The ID of the Play that the Moment references
1641
1635
  //
1642
- pub fun setMomentsSubedition(nftID: UInt64, subeditionID: UInt32, setID: UInt32, playID: UInt32){
1636
+ access(all) fun setMomentsSubedition(nftID: UInt64, subeditionID: UInt32, setID: UInt32, playID: UInt32){
1643
1637
  pre {
1644
1638
  !self.momentsSubedition.containsKey(nftID) : "Subedition for this moment already exists!"
1645
1639
  }
@@ -1657,6 +1651,74 @@ pub contract TopShot: NonFungibleToken {
1657
1651
  }
1658
1652
  }
1659
1653
 
1654
+ //------------------------------------------------------------
1655
+ // Contract MetadataViews
1656
+ //------------------------------------------------------------
1657
+
1658
+ /// Return the metadata view types available for this contract
1659
+ ///
1660
+ access(all) view fun getContractViews(resourceType: Type?): [Type] {
1661
+ return [Type<MetadataViews.NFTCollectionData>(), Type<MetadataViews.NFTCollectionDisplay>(), Type<MetadataViews.Royalties>()]
1662
+ }
1663
+
1664
+ /// Resolve this contract's metadata views
1665
+ ///
1666
+ access(all) view fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
1667
+ post {
1668
+ result == nil || result!.getType() == viewType: "The returned view must be of the given type or nil"
1669
+ }
1670
+ switch viewType {
1671
+ case Type<MetadataViews.NFTCollectionData>():
1672
+ return MetadataViews.NFTCollectionData(
1673
+ storagePath: /storage/MomentCollection,
1674
+ publicPath: /public/MomentCollection,
1675
+ publicCollection: Type<&TopShot.Collection>(),
1676
+ publicLinkedType: Type<&TopShot.Collection>(),
1677
+ createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} {
1678
+ return <-TopShot.createEmptyCollection(nftType: Type<@TopShot.NFT>())
1679
+ })
1680
+ )
1681
+ case Type<MetadataViews.NFTCollectionDisplay>():
1682
+ let bannerImage = MetadataViews.Media(
1683
+ file: MetadataViews.HTTPFile(
1684
+ url: "https://nbatopshot.com/static/img/top-shot-logo-horizontal-white.svg"
1685
+ ),
1686
+ mediaType: "image/svg+xml"
1687
+ )
1688
+ let squareImage = MetadataViews.Media(
1689
+ file: MetadataViews.HTTPFile(
1690
+ url: "https://nbatopshot.com/static/img/og/og.png"
1691
+ ),
1692
+ mediaType: "image/png"
1693
+ )
1694
+ return MetadataViews.NFTCollectionDisplay(
1695
+ name: "NBA-Top-Shot",
1696
+ description: "NBA Top Shot is your chance to own, sell, and trade official digital collectibles of the NBA and WNBA's greatest plays and players",
1697
+ externalURL: MetadataViews.ExternalURL("https://nbatopshot.com"),
1698
+ squareImage: squareImage,
1699
+ bannerImage: bannerImage,
1700
+ socials: {
1701
+ "twitter": MetadataViews.ExternalURL("https://twitter.com/nbatopshot"),
1702
+ "discord": MetadataViews.ExternalURL("https://discord.com/invite/nbatopshot"),
1703
+ "instagram": MetadataViews.ExternalURL("https://www.instagram.com/nbatopshot")
1704
+ }
1705
+ )
1706
+ case Type<MetadataViews.Royalties>():
1707
+ let royaltyReceiver: Capability<&{FungibleToken.Receiver}> =
1708
+ getAccount(TopShot.RoyaltyAddress()).capabilities.get<&{FungibleToken.Receiver}>(MetadataViews.getRoyaltyReceiverPublicPath())!
1709
+ return MetadataViews.Royalties(
1710
+ [
1711
+ MetadataViews.Royalty(
1712
+ receiver: royaltyReceiver,
1713
+ cut: 0.05,
1714
+ description: "NBATopShot marketplace royalty"
1715
+ )
1716
+ ]
1717
+ )
1718
+ }
1719
+ return nil
1720
+ }
1721
+
1660
1722
 
1661
1723
  // -----------------------------------------------------------------------
1662
1724
  // TopShot initialization function
@@ -1673,13 +1735,15 @@ pub contract TopShot: NonFungibleToken {
1673
1735
  self.totalSupply = 0
1674
1736
 
1675
1737
  // Put a new Collection in storage
1676
- self.account.save<@Collection>(<- create Collection(), to: /storage/MomentCollection)
1738
+ self.account.storage.save<@Collection>(<- create Collection(), to: /storage/MomentCollection)
1677
1739
 
1678
1740
  // Create a public capability for the Collection
1679
- self.account.link<&{MomentCollectionPublic}>(/public/MomentCollection, target: /storage/MomentCollection)
1741
+ let cap = self.account.capabilities.storage.issue<&TopShot.Collection>(/storage/MomentCollection)
1742
+ self.account.capabilities.publish(cap, at: /public/MomentCollection)
1743
+ //self.account.link<&{MomentCollectionPublic}>(/public/MomentCollection, target: /storage/MomentCollection)
1680
1744
 
1681
1745
  // Put the Minter in storage
1682
- self.account.save<@Admin>(<- create Admin(), to: /storage/TopShotAdmin)
1746
+ self.account.storage.save<@Admin>(<- create Admin(), to: /storage/TopShotAdmin)
1683
1747
 
1684
1748
  emit ContractInitialized()
1685
1749
  }