@flowtyio/flow-contracts 0.0.10 → 0.0.14

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.
@@ -0,0 +1,42 @@
1
+ import "LostAndFound"
2
+
3
+ pub contract LostAndFoundHelper {
4
+
5
+ pub struct Ticket {
6
+
7
+ // An optional message to attach to this item.
8
+ pub let memo: String?
9
+ // The address that it allowed to withdraw the item fromt this ticket
10
+ pub let redeemer: Address
11
+ //The type of the resource (non-optional) so that bins can represent the true type of an item
12
+ pub let type: Type
13
+ pub let typeIdentifier: String
14
+ // State maintained by LostAndFound
15
+ pub let redeemed: Bool
16
+ pub let name : String?
17
+ pub let description : String?
18
+ pub let thumbnail : String?
19
+ pub let ticketID : UInt64?
20
+
21
+ init(_ ticket: &LostAndFound.Ticket, id: UInt64?) {
22
+ self.memo = ticket.memo
23
+ self.redeemer = ticket.redeemer
24
+ self.type = ticket.type
25
+ self.typeIdentifier = ticket.type.identifier
26
+ self.redeemed = ticket.redeemed
27
+ self.name = ticket.display?.name
28
+ self.description = ticket.display?.description
29
+ self.thumbnail = ticket.display?.thumbnail?.uri()
30
+ self.ticketID = id
31
+ }
32
+
33
+ }
34
+
35
+ pub fun constructResult(_ ticket: &LostAndFound.Ticket?, id:UInt64?) : LostAndFoundHelper.Ticket? {
36
+ if ticket != nil {
37
+ return LostAndFoundHelper.Ticket(ticket!, id: id)
38
+ }
39
+ return nil
40
+ }
41
+
42
+ }
@@ -0,0 +1,422 @@
1
+ import "MetadataViews"
2
+
3
+ // NFTCatalog
4
+ //
5
+ // A general purpose NFT registry for Flow NonFungibleTokens.
6
+ //
7
+ // Each catalog entry stores data about the NFT including
8
+ // its collection identifier, nft type, storage and public paths, etc.
9
+ //
10
+ // To make an addition to the catalog you can propose an NFT and provide its metadata.
11
+ // An Admin can approve a proposal which would add the NFT to the catalog
12
+
13
+ pub contract NFTCatalog {
14
+ // EntryAdded
15
+ // An NFT collection has been added to the catalog
16
+ pub event EntryAdded(
17
+ collectionIdentifier : String,
18
+ contractName : String,
19
+ contractAddress : Address,
20
+ nftType : Type,
21
+ storagePath: StoragePath,
22
+ publicPath: PublicPath,
23
+ privatePath: PrivatePath,
24
+ publicLinkedType : Type,
25
+ privateLinkedType : Type,
26
+ displayName : String,
27
+ description: String,
28
+ externalURL : String
29
+ )
30
+
31
+ // EntryUpdated
32
+ // An NFT Collection has been updated in the catalog
33
+ pub event EntryUpdated(
34
+ collectionIdentifier : String,
35
+ contractName : String,
36
+ contractAddress : Address,
37
+ nftType : Type,
38
+ storagePath: StoragePath,
39
+ publicPath: PublicPath,
40
+ privatePath: PrivatePath,
41
+ publicLinkedType : Type,
42
+ privateLinkedType : Type,
43
+ displayName : String,
44
+ description: String,
45
+ externalURL : String
46
+ )
47
+
48
+ // EntryRemoved
49
+ // An NFT Collection has been removed from the catalog
50
+ pub event EntryRemoved(collectionIdentifier : String, nftType: Type)
51
+
52
+ // ProposalEntryAdded
53
+ // A new proposal to make an addtion to the catalog has been made
54
+ pub event ProposalEntryAdded(proposalID : UInt64, collectionIdentifier : String, message: String, status: String, proposer : Address)
55
+
56
+ // ProposalEntryUpdated
57
+ // A proposal has been updated
58
+ pub event ProposalEntryUpdated(proposalID : UInt64, collectionIdentifier : String, message: String, status: String, proposer : Address)
59
+
60
+ // ProposalEntryRemoved
61
+ // A proposal has been removed from storage
62
+ pub event ProposalEntryRemoved(proposalID : UInt64)
63
+
64
+ pub let ProposalManagerStoragePath: StoragePath
65
+
66
+ pub let ProposalManagerPublicPath: PublicPath
67
+
68
+ access(self) let catalog: {String : NFTCatalog.NFTCatalogMetadata} // { collectionIdentifier -> Metadata }
69
+ access(self) let catalogTypeData: {String : {String : Bool}} // Additional view to go from { NFT Type Identifier -> {Collection Identifier : Bool } }
70
+
71
+ access(self) let catalogProposals : {UInt64 : NFTCatalogProposal} // { ProposalID : Metadata }
72
+
73
+ access(self) var totalProposals : UInt64
74
+
75
+ // NFTCatalogProposalManager
76
+ // Used to authenticate proposals made to the catalog
77
+
78
+ pub resource interface NFTCatalogProposalManagerPublic {
79
+ pub fun getCurrentProposalEntry(): String?
80
+ }
81
+ pub resource NFTCatalogProposalManager : NFTCatalogProposalManagerPublic {
82
+ access(self) var currentProposalEntry: String?
83
+
84
+ pub fun getCurrentProposalEntry(): String? {
85
+ return self.currentProposalEntry
86
+ }
87
+
88
+ pub fun setCurrentProposalEntry(identifier: String?) {
89
+ self.currentProposalEntry = identifier
90
+ }
91
+
92
+ init () {
93
+ self.currentProposalEntry = nil
94
+ }
95
+ }
96
+
97
+
98
+ pub resource Snapshot {
99
+ pub var catalogSnapshot: {String : NFTCatalogMetadata}
100
+ pub var shouldUseSnapshot: Bool
101
+
102
+ pub fun setPartialSnapshot(_ snapshotKey: String, _ snapshotEntry: NFTCatalogMetadata) {
103
+ self.catalogSnapshot[snapshotKey] = snapshotEntry
104
+ }
105
+
106
+ pub fun setShouldUseSnapshot(_ shouldUseSnapshot: Bool) {
107
+ self.shouldUseSnapshot = shouldUseSnapshot
108
+ }
109
+
110
+ pub fun getCatalogSnapshot(): {String : NFTCatalogMetadata} {
111
+ return self.catalogSnapshot
112
+ }
113
+
114
+ init() {
115
+ self.shouldUseSnapshot = false
116
+ self.catalogSnapshot = {}
117
+ }
118
+ }
119
+
120
+ pub fun createEmptySnapshot(): @Snapshot {
121
+ return <- create Snapshot()
122
+ }
123
+
124
+ // NFTCollectionData
125
+ // Represents information about an NFT collection resource
126
+ // Note: Not suing the struct from Metadata standard due to
127
+ // inability to store functions
128
+ pub struct NFTCollectionData {
129
+
130
+ pub let storagePath : StoragePath
131
+ pub let publicPath : PublicPath
132
+ pub let privatePath: PrivatePath
133
+ pub let publicLinkedType: Type
134
+ pub let privateLinkedType: Type
135
+
136
+ init(
137
+ storagePath : StoragePath,
138
+ publicPath : PublicPath,
139
+ privatePath : PrivatePath,
140
+ publicLinkedType : Type,
141
+ privateLinkedType : Type
142
+ ) {
143
+ self.storagePath = storagePath
144
+ self.publicPath = publicPath
145
+ self.privatePath = privatePath
146
+ self.publicLinkedType = publicLinkedType
147
+ self.privateLinkedType = privateLinkedType
148
+ }
149
+ }
150
+
151
+ // NFTCatalogMetadata
152
+ // Represents data about an NFT
153
+ pub struct NFTCatalogMetadata {
154
+ pub let contractName : String
155
+ pub let contractAddress : Address
156
+ pub let nftType: Type
157
+ pub let collectionData: NFTCollectionData
158
+ pub let collectionDisplay: MetadataViews.NFTCollectionDisplay
159
+
160
+ init (contractName : String, contractAddress : Address, nftType: Type, collectionData : NFTCollectionData, collectionDisplay : MetadataViews.NFTCollectionDisplay) {
161
+ self.contractName = contractName
162
+ self.contractAddress = contractAddress
163
+ self.nftType = nftType
164
+ self.collectionData = collectionData
165
+ self.collectionDisplay = collectionDisplay
166
+ }
167
+ }
168
+
169
+ // NFTCatalogProposal
170
+ // Represents a proposal to the catalog
171
+ // Includes data about an NFT
172
+ pub struct NFTCatalogProposal {
173
+ pub let collectionIdentifier : String
174
+ pub let metadata : NFTCatalogMetadata
175
+ pub let message : String
176
+ pub let status : String
177
+ pub let proposer : Address
178
+ pub let createdTime : UFix64
179
+
180
+ init(collectionIdentifier : String, metadata : NFTCatalogMetadata, message : String, status : String, proposer : Address) {
181
+ self.collectionIdentifier = collectionIdentifier
182
+ self.metadata = metadata
183
+ self.message = message
184
+ self.status = status
185
+ self.proposer = proposer
186
+ self.createdTime = getCurrentBlock().timestamp
187
+ }
188
+ }
189
+
190
+ /*
191
+ DEPRECATED
192
+ If obtaining all elements from the catalog is essential, please
193
+ use the getCatalogKeys and forEachCatalogKey methods instead.
194
+ */
195
+ pub fun getCatalog() : {String : NFTCatalogMetadata} {
196
+ let snapshot = self.account.borrow<&NFTCatalog.Snapshot>(from: /storage/CatalogSnapshot)
197
+ if snapshot != nil {
198
+ let snapshot = snapshot!
199
+ if snapshot.shouldUseSnapshot {
200
+ return snapshot.getCatalogSnapshot()
201
+ } else {
202
+ return self.catalog
203
+ }
204
+ } else {
205
+ return self.catalog
206
+ }
207
+ }
208
+
209
+ pub fun getCatalogKeys(): [String] {
210
+ return self.catalog.keys
211
+ }
212
+
213
+ pub fun forEachCatalogKey(_ function: ((String): Bool)) {
214
+ self.catalog.forEachKey(function)
215
+ }
216
+
217
+ pub fun getCatalogEntry(collectionIdentifier : String) : NFTCatalogMetadata? {
218
+ return self.catalog[collectionIdentifier]
219
+ }
220
+
221
+ pub fun getCollectionsForType(nftTypeIdentifier: String) : {String : Bool}? {
222
+ return self.catalogTypeData[nftTypeIdentifier]
223
+ }
224
+
225
+ pub fun getCatalogTypeData() : {String : {String : Bool}} {
226
+ return self.catalogTypeData
227
+ }
228
+
229
+ // Propose an NFT collection to the catalog
230
+ // @param collectionIdentifier: The unique name assinged to this nft collection
231
+ // @param metadata: The Metadata for the NFT collection that will be stored in the catalog
232
+ // @param message: A message to the catalog owners
233
+ // @param proposer: Who is making the proposition(the address needs to be verified)
234
+ pub fun proposeNFTMetadata(collectionIdentifier : String, metadata : NFTCatalogMetadata, message : String, proposer : Address) : UInt64 {
235
+ let proposerManagerCap = getAccount(proposer).getCapability<&NFTCatalogProposalManager{NFTCatalog.NFTCatalogProposalManagerPublic}>(NFTCatalog.ProposalManagerPublicPath)
236
+
237
+ assert(proposerManagerCap.check(), message : "Proposer needs to set up a manager")
238
+
239
+ let proposerManagerRef = proposerManagerCap.borrow()!
240
+
241
+ assert(proposerManagerRef.getCurrentProposalEntry()! == collectionIdentifier, message: "Expected proposal entry does not match entry for the proposer")
242
+
243
+ let catalogProposal = NFTCatalogProposal(collectionIdentifier : collectionIdentifier, metadata : metadata, message : message, status: "IN_REVIEW", proposer: proposer)
244
+ self.totalProposals = self.totalProposals + 1
245
+ self.catalogProposals[self.totalProposals] = catalogProposal
246
+
247
+ emit ProposalEntryAdded(proposalID : self.totalProposals, collectionIdentifier : collectionIdentifier, message: catalogProposal.message, status: catalogProposal.status, proposer: catalogProposal.proposer)
248
+ return self.totalProposals
249
+ }
250
+
251
+ // Withdraw a proposal from the catalog
252
+ // @param proposalID: The ID of proposal you want to withdraw
253
+ pub fun withdrawNFTProposal(proposalID : UInt64) {
254
+ pre {
255
+ self.catalogProposals[proposalID] != nil : "Invalid Proposal ID"
256
+ }
257
+ let proposal = self.catalogProposals[proposalID]!
258
+ let proposer = proposal.proposer
259
+
260
+ let proposerManagerCap = getAccount(proposer).getCapability<&NFTCatalogProposalManager{NFTCatalog.NFTCatalogProposalManagerPublic}>(NFTCatalog.ProposalManagerPublicPath)
261
+
262
+ assert(proposerManagerCap.check(), message : "Proposer needs to set up a manager")
263
+
264
+ let proposerManagerRef = proposerManagerCap.borrow()!
265
+
266
+ assert(proposerManagerRef.getCurrentProposalEntry()! == proposal.collectionIdentifier, message: "Expected proposal entry does not match entry for the proposer")
267
+
268
+ self.removeCatalogProposal(proposalID : proposalID)
269
+ }
270
+
271
+ pub fun getCatalogProposals() : {UInt64 : NFTCatalogProposal} {
272
+ return self.catalogProposals
273
+ }
274
+
275
+ pub fun getCatalogProposalEntry(proposalID : UInt64) : NFTCatalogProposal? {
276
+ return self.catalogProposals[proposalID]
277
+ }
278
+
279
+ pub fun getCatalogProposalKeys() : [UInt64] {
280
+ return self.catalogProposals.keys
281
+ }
282
+
283
+ pub fun forEachCatalogProposalKey(_ function: ((UInt64): Bool)) {
284
+ self.catalogProposals.forEachKey(function)
285
+ }
286
+
287
+ pub fun createNFTCatalogProposalManager(): @NFTCatalogProposalManager {
288
+ return <-create NFTCatalogProposalManager()
289
+ }
290
+
291
+ access(account) fun addCatalogEntry(collectionIdentifier : String, metadata: NFTCatalogMetadata) {
292
+ pre {
293
+ self.catalog[collectionIdentifier] == nil : "The nft name has already been added to the catalog"
294
+ }
295
+
296
+ self.addCatalogTypeEntry(collectionIdentifier : collectionIdentifier , metadata: metadata)
297
+
298
+ self.catalog[collectionIdentifier] = metadata
299
+
300
+ emit EntryAdded(
301
+ collectionIdentifier : collectionIdentifier,
302
+ contractName : metadata.contractName,
303
+ contractAddress : metadata.contractAddress,
304
+ nftType: metadata.nftType,
305
+ storagePath: metadata.collectionData.storagePath,
306
+ publicPath: metadata.collectionData.publicPath,
307
+ privatePath: metadata.collectionData.privatePath,
308
+ publicLinkedType : metadata.collectionData.publicLinkedType,
309
+ privateLinkedType : metadata.collectionData.privateLinkedType,
310
+ displayName : metadata.collectionDisplay.name,
311
+ description: metadata.collectionDisplay.description,
312
+ externalURL : metadata.collectionDisplay.externalURL.url
313
+ )
314
+ }
315
+
316
+ access(account) fun updateCatalogEntry(collectionIdentifier : String , metadata: NFTCatalogMetadata) {
317
+ pre {
318
+ self.catalog[collectionIdentifier] != nil : "Invalid collection identifier"
319
+ }
320
+ // remove previous nft type entry
321
+ self.removeCatalogTypeEntry(collectionIdentifier : collectionIdentifier , metadata: metadata)
322
+ // add updated nft type entry
323
+ self.addCatalogTypeEntry(collectionIdentifier : collectionIdentifier , metadata: metadata)
324
+
325
+ self.catalog[collectionIdentifier] = metadata
326
+
327
+ let nftType = metadata.nftType
328
+
329
+ emit EntryUpdated(
330
+ collectionIdentifier : collectionIdentifier,
331
+ contractName : metadata.contractName,
332
+ contractAddress : metadata.contractAddress,
333
+ nftType: metadata.nftType,
334
+ storagePath: metadata.collectionData.storagePath,
335
+ publicPath: metadata.collectionData.publicPath,
336
+ privatePath: metadata.collectionData.privatePath,
337
+ publicLinkedType : metadata.collectionData.publicLinkedType,
338
+ privateLinkedType : metadata.collectionData.privateLinkedType,
339
+ displayName : metadata.collectionDisplay.name,
340
+ description: metadata.collectionDisplay.description,
341
+ externalURL : metadata.collectionDisplay.externalURL.url
342
+ )
343
+ }
344
+
345
+ access(account) fun removeCatalogEntry(collectionIdentifier : String) {
346
+ pre {
347
+ self.catalog[collectionIdentifier] != nil : "Invalid collection identifier"
348
+ }
349
+
350
+ let removedType = self.removeCatalogTypeEntry(collectionIdentifier : collectionIdentifier , metadata: self.catalog[collectionIdentifier]!)
351
+ self.catalog.remove(key: collectionIdentifier)
352
+
353
+ emit EntryRemoved(collectionIdentifier : collectionIdentifier, nftType: removedType)
354
+ }
355
+
356
+ // This function is not preferred, and was used for the following issue:
357
+ // https://github.com/onflow/cadence/issues/2649
358
+ // If a contract's type is no longer resolvable in cadence and crashing,
359
+ // this function can be used to remove it from the catalog.
360
+ access(account) fun removeCatalogEntryUnsafe(collectionIdentifier: String, nftTypeIdentifier: String) {
361
+ // Remove the catalog entry
362
+ self.catalog.remove(key: collectionIdentifier)
363
+
364
+ // Remove the type entry
365
+ if (self.catalogTypeData[nftTypeIdentifier]!.keys.length == 1) {
366
+ self.catalogTypeData.remove(key: nftTypeIdentifier)
367
+ } else {
368
+ self.catalogTypeData[nftTypeIdentifier]!.remove(key: collectionIdentifier)
369
+ }
370
+ }
371
+
372
+ access(account) fun updateCatalogProposal(proposalID: UInt64, proposalMetadata : NFTCatalogProposal) {
373
+ self.catalogProposals[proposalID] = proposalMetadata
374
+
375
+ emit ProposalEntryUpdated(proposalID : proposalID, collectionIdentifier : proposalMetadata.collectionIdentifier, message: proposalMetadata.message, status: proposalMetadata.status, proposer: proposalMetadata.proposer)
376
+ }
377
+
378
+ access(account) fun removeCatalogProposal(proposalID : UInt64) {
379
+ self.catalogProposals.remove(key : proposalID)
380
+
381
+ emit ProposalEntryRemoved(proposalID : proposalID)
382
+ }
383
+
384
+ access(contract) fun addCatalogTypeEntry(collectionIdentifier : String , metadata: NFTCatalogMetadata) {
385
+ if self.catalogTypeData[metadata.nftType.identifier] != nil {
386
+ let typeData : {String : Bool} = self.catalogTypeData[metadata.nftType.identifier]!
387
+ assert(self.catalogTypeData[metadata.nftType.identifier]![collectionIdentifier] == nil, message : "The nft name has already been added to the catalog")
388
+ typeData[collectionIdentifier] = true
389
+ self.catalogTypeData[metadata.nftType.identifier] = typeData
390
+ } else {
391
+ let typeData : {String : Bool} = {}
392
+ typeData[collectionIdentifier] = true
393
+ self.catalogTypeData[metadata.nftType.identifier] = typeData
394
+ }
395
+ }
396
+
397
+ access(contract) fun removeCatalogTypeEntry(collectionIdentifier : String , metadata: NFTCatalogMetadata): Type {
398
+ let prevMetadata = self.catalog[collectionIdentifier]!
399
+ let prevCollectionsForType = self.catalogTypeData[prevMetadata.nftType.identifier]!
400
+ prevCollectionsForType.remove(key : collectionIdentifier)
401
+ if prevCollectionsForType.length == 0 {
402
+ self.catalogTypeData.remove(key: prevMetadata.nftType.identifier)
403
+ } else {
404
+ self.catalogTypeData[prevMetadata.nftType.identifier] = prevCollectionsForType
405
+ }
406
+
407
+ return metadata.nftType
408
+ }
409
+
410
+ init() {
411
+ self.ProposalManagerStoragePath = /storage/nftCatalogProposalManager
412
+ self.ProposalManagerPublicPath = /public/nftCatalogProposalManager
413
+
414
+ self.totalProposals = 0
415
+ self.catalog = {}
416
+ self.catalogTypeData = {}
417
+
418
+ self.catalogProposals = {}
419
+ }
420
+
421
+ }
422
+
@@ -0,0 +1,175 @@
1
+ import "NFTCatalog"
2
+
3
+ // NFTCatalogAdmin
4
+ //
5
+ // An admin contract that defines an admin resource and
6
+ // a proxy resource to receive a capability that lets you make changes to the NFT Catalog
7
+ // and manage proposals
8
+
9
+ pub contract NFTCatalogAdmin {
10
+
11
+ // AddProposalAccepted
12
+ // Emitted when a proposal to add a new catalog item has been approved by an admin
13
+ pub event AddProposalAccepted(
14
+ proposer: Address,
15
+ collectionIdentifier : String,
16
+ contractName : String,
17
+ contractAddress : Address,
18
+ displayName : String
19
+ )
20
+
21
+ // UpdateProposalAccepted
22
+ // Emitted when a proposal to update a catalog item has been approved by an admin
23
+ pub event UpdateProposalAccepted(
24
+ proposer: Address,
25
+ collectionIdentifier : String,
26
+ contractName : String,
27
+ contractAddress : Address,
28
+ displayName : String
29
+ )
30
+
31
+ // ProposalRejected
32
+ // Emitted when a proposal to add or update a catalog item has been rejected.
33
+ pub event ProposalRejected(
34
+ proposer: Address,
35
+ collectionIdentifier : String,
36
+ contractName : String,
37
+ contractAddress : Address,
38
+ displayName : String
39
+ )
40
+
41
+ pub let AdminPrivatePath: PrivatePath
42
+ pub let AdminStoragePath: StoragePath
43
+
44
+ pub let AdminProxyPublicPath: PublicPath
45
+ pub let AdminProxyStoragePath: StoragePath
46
+
47
+ // Admin
48
+ // Admin resource to manage NFT Catalog
49
+ pub resource Admin {
50
+
51
+ pub fun addCatalogEntry(collectionIdentifier: String, metadata : NFTCatalog.NFTCatalogMetadata) {
52
+ NFTCatalog.addCatalogEntry(collectionIdentifier: collectionIdentifier, metadata : metadata)
53
+ }
54
+
55
+ pub fun updateCatalogEntry(collectionIdentifier : String , metadata : NFTCatalog.NFTCatalogMetadata) {
56
+ NFTCatalog.updateCatalogEntry(collectionIdentifier: collectionIdentifier, metadata : metadata)
57
+ }
58
+
59
+ pub fun removeCatalogEntry(collectionIdentifier : String) {
60
+ NFTCatalog.removeCatalogEntry(collectionIdentifier : collectionIdentifier)
61
+ }
62
+
63
+ pub fun removeCatalogEntryUnsafe(collectionIdentifier : String, nftTypeIdentifier: String) {
64
+ NFTCatalog.removeCatalogEntryUnsafe(collectionIdentifier : collectionIdentifier, nftTypeIdentifier: nftTypeIdentifier)
65
+ }
66
+
67
+ pub fun approveCatalogProposal(proposalID : UInt64) {
68
+ pre {
69
+ NFTCatalog.getCatalogProposalEntry(proposalID : proposalID) != nil : "Invalid Proposal ID"
70
+ NFTCatalog.getCatalogProposalEntry(proposalID : proposalID)!.status == "IN_REVIEW" : "Invalid Proposal"
71
+ }
72
+ let catalogProposalEntry = NFTCatalog.getCatalogProposalEntry(proposalID : proposalID)!
73
+ let newCatalogProposalEntry = NFTCatalog.NFTCatalogProposal(collectionIdentifier : catalogProposalEntry.collectionIdentifier, metadata : catalogProposalEntry.metadata, message : catalogProposalEntry.message, status: "APPROVED", proposer: catalogProposalEntry.proposer)
74
+ NFTCatalog.updateCatalogProposal(proposalID : proposalID, proposalMetadata : newCatalogProposalEntry)
75
+
76
+ if NFTCatalog.getCatalogEntry(collectionIdentifier : NFTCatalog.getCatalogProposalEntry(proposalID : proposalID)!.collectionIdentifier) == nil {
77
+ NFTCatalog.addCatalogEntry(collectionIdentifier: newCatalogProposalEntry.collectionIdentifier, metadata : newCatalogProposalEntry.metadata)
78
+ emit AddProposalAccepted(
79
+ proposer: newCatalogProposalEntry.proposer,
80
+ collectionIdentifier : newCatalogProposalEntry.collectionIdentifier,
81
+ contractName : newCatalogProposalEntry.metadata.contractName,
82
+ contractAddress : newCatalogProposalEntry.metadata.contractAddress,
83
+ displayName : newCatalogProposalEntry.metadata.collectionDisplay.name
84
+ )
85
+ } else {
86
+ NFTCatalog.updateCatalogEntry(collectionIdentifier: newCatalogProposalEntry.collectionIdentifier, metadata: newCatalogProposalEntry.metadata)
87
+ emit UpdateProposalAccepted(
88
+ proposer: newCatalogProposalEntry.proposer,
89
+ collectionIdentifier : newCatalogProposalEntry.collectionIdentifier,
90
+ contractName : newCatalogProposalEntry.metadata.contractName,
91
+ contractAddress : newCatalogProposalEntry.metadata.contractAddress,
92
+ displayName : newCatalogProposalEntry.metadata.collectionDisplay.name
93
+ )
94
+ }
95
+ }
96
+
97
+ pub fun rejectCatalogProposal(proposalID : UInt64) {
98
+ pre {
99
+ NFTCatalog.getCatalogProposalEntry(proposalID : proposalID) != nil : "Invalid Proposal ID"
100
+ NFTCatalog.getCatalogProposalEntry(proposalID : proposalID)!.status == "IN_REVIEW" : "Invalid Proposal"
101
+ }
102
+ let catalogProposalEntry = NFTCatalog.getCatalogProposalEntry(proposalID : proposalID)!
103
+ let newCatalogProposalEntry = NFTCatalog.NFTCatalogProposal(collectionIdentifier : catalogProposalEntry.collectionIdentifier, metadata : catalogProposalEntry.metadata, message : catalogProposalEntry.message, status: "REJECTED", proposer: catalogProposalEntry.proposer)
104
+ NFTCatalog.updateCatalogProposal(proposalID : proposalID, proposalMetadata : newCatalogProposalEntry)
105
+ emit ProposalRejected(
106
+ proposer: newCatalogProposalEntry.proposer,
107
+ collectionIdentifier : newCatalogProposalEntry.collectionIdentifier,
108
+ contractName : newCatalogProposalEntry.metadata.contractName,
109
+ contractAddress : newCatalogProposalEntry.metadata.contractAddress,
110
+ displayName : newCatalogProposalEntry.metadata.collectionDisplay.name
111
+ )
112
+ }
113
+
114
+ pub fun removeCatalogProposal(proposalID : UInt64) {
115
+ pre {
116
+ NFTCatalog.getCatalogProposalEntry(proposalID : proposalID) != nil : "Invalid Proposal ID"
117
+ }
118
+ NFTCatalog.removeCatalogProposal(proposalID : proposalID)
119
+ }
120
+
121
+ init () {}
122
+
123
+ }
124
+
125
+ // AdminProxy
126
+ // A proxy resource that can store
127
+ // a capability to admin controls
128
+ pub resource interface IAdminProxy {
129
+ pub fun addCapability(capability : Capability<&Admin>)
130
+ pub fun hasCapability() : Bool
131
+ }
132
+
133
+ pub resource AdminProxy : IAdminProxy {
134
+
135
+ access(self) var capability : Capability<&Admin>?
136
+
137
+ pub fun addCapability(capability : Capability<&Admin>) {
138
+ pre {
139
+ capability.check() : "Invalid Admin Capability"
140
+ self.capability == nil : "Admin Proxy already set"
141
+ }
142
+ self.capability = capability
143
+ }
144
+
145
+ pub fun getCapability() : Capability<&Admin>? {
146
+ return self.capability
147
+ }
148
+
149
+ pub fun hasCapability() : Bool {
150
+ return self.capability != nil
151
+ }
152
+
153
+ init() {
154
+ self.capability = nil
155
+ }
156
+
157
+ }
158
+
159
+ pub fun createAdminProxy() : @AdminProxy {
160
+ return <- create AdminProxy()
161
+ }
162
+
163
+ init () {
164
+ self.AdminProxyPublicPath = /public/nftCatalogAdminProxy
165
+ self.AdminProxyStoragePath = /storage/nftCatalogAdminProxy
166
+
167
+ self.AdminPrivatePath = /private/nftCatalogAdmin
168
+ self.AdminStoragePath = /storage/nftCatalogAdmin
169
+
170
+ let admin <- create Admin()
171
+
172
+ self.account.save(<-admin, to: self.AdminStoragePath)
173
+ self.account.link<&Admin>(self.AdminPrivatePath, target: self.AdminStoragePath)
174
+ }
175
+ }