@flowtyio/flow-contracts 0.0.18 → 0.1.0-beta.2
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.
- package/contracts/FlowStorageFees.cdc +49 -51
- package/contracts/FlowToken.cdc +90 -53
- package/contracts/FungibleToken.cdc +91 -127
- package/contracts/FungibleTokenMetadataViews.cdc +52 -43
- package/contracts/MetadataViews.cdc +345 -363
- package/contracts/NonFungibleToken.cdc +93 -104
- package/contracts/ViewResolver.cdc +34 -5
- package/contracts/lost-and-found/FeeEstimator.cdc +14 -22
- package/contracts/lost-and-found/LostAndFound.cdc +185 -177
- package/contracts/lost-and-found/LostAndFoundHelper.cdc +12 -12
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import "FungibleToken"
|
|
2
2
|
import "NonFungibleToken"
|
|
3
|
+
import "ViewResolver"
|
|
3
4
|
|
|
4
5
|
/// This contract implements the metadata standard proposed
|
|
5
6
|
/// in FLIP-0636.
|
|
@@ -11,113 +12,38 @@ import "NonFungibleToken"
|
|
|
11
12
|
/// a different kind of metadata, such as a creator biography
|
|
12
13
|
/// or a JPEG image file.
|
|
13
14
|
///
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
/// Provides access to a set of metadata views. A struct or
|
|
17
|
-
/// resource (e.g. an NFT) can implement this interface to provide access to
|
|
18
|
-
/// the views that it supports.
|
|
19
|
-
///
|
|
20
|
-
pub resource interface Resolver {
|
|
21
|
-
pub fun getViews(): [Type]
|
|
22
|
-
pub fun resolveView(_ view: Type): AnyStruct?
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/// A group of view resolvers indexed by ID.
|
|
26
|
-
///
|
|
27
|
-
pub resource interface ResolverCollection {
|
|
28
|
-
pub fun borrowViewResolver(id: UInt64): &{Resolver}
|
|
29
|
-
pub fun getIDs(): [UInt64]
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/// NFTView wraps all Core views along `id` and `uuid` fields, and is used
|
|
33
|
-
/// to give a complete picture of an NFT. Most NFTs should implement this
|
|
34
|
-
/// view.
|
|
35
|
-
///
|
|
36
|
-
pub struct NFTView {
|
|
37
|
-
pub let id: UInt64
|
|
38
|
-
pub let uuid: UInt64
|
|
39
|
-
pub let display: Display?
|
|
40
|
-
pub let externalURL: ExternalURL?
|
|
41
|
-
pub let collectionData: NFTCollectionData?
|
|
42
|
-
pub let collectionDisplay: NFTCollectionDisplay?
|
|
43
|
-
pub let royalties: Royalties?
|
|
44
|
-
pub let traits: Traits?
|
|
45
|
-
|
|
46
|
-
init(
|
|
47
|
-
id : UInt64,
|
|
48
|
-
uuid : UInt64,
|
|
49
|
-
display : Display?,
|
|
50
|
-
externalURL : ExternalURL?,
|
|
51
|
-
collectionData : NFTCollectionData?,
|
|
52
|
-
collectionDisplay : NFTCollectionDisplay?,
|
|
53
|
-
royalties : Royalties?,
|
|
54
|
-
traits: Traits?
|
|
55
|
-
) {
|
|
56
|
-
self.id = id
|
|
57
|
-
self.uuid = uuid
|
|
58
|
-
self.display = display
|
|
59
|
-
self.externalURL = externalURL
|
|
60
|
-
self.collectionData = collectionData
|
|
61
|
-
self.collectionDisplay = collectionDisplay
|
|
62
|
-
self.royalties = royalties
|
|
63
|
-
self.traits = traits
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/// Helper to get an NFT view
|
|
68
|
-
///
|
|
69
|
-
/// @param id: The NFT id
|
|
70
|
-
/// @param viewResolver: A reference to the resolver resource
|
|
71
|
-
/// @return A NFTView struct
|
|
72
|
-
///
|
|
73
|
-
pub fun getNFTView(id: UInt64, viewResolver: &{Resolver}) : NFTView {
|
|
74
|
-
let nftView = viewResolver.resolveView(Type<NFTView>())
|
|
75
|
-
if nftView != nil {
|
|
76
|
-
return nftView! as! NFTView
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return NFTView(
|
|
80
|
-
id : id,
|
|
81
|
-
uuid: viewResolver.uuid,
|
|
82
|
-
display: self.getDisplay(viewResolver),
|
|
83
|
-
externalURL : self.getExternalURL(viewResolver),
|
|
84
|
-
collectionData : self.getNFTCollectionData(viewResolver),
|
|
85
|
-
collectionDisplay : self.getNFTCollectionDisplay(viewResolver),
|
|
86
|
-
royalties : self.getRoyalties(viewResolver),
|
|
87
|
-
traits : self.getTraits(viewResolver)
|
|
88
|
-
)
|
|
89
|
-
}
|
|
15
|
+
access(all) contract MetadataViews {
|
|
90
16
|
|
|
91
17
|
/// Display is a basic view that includes the name, description and
|
|
92
18
|
/// thumbnail for an object. Most objects should implement this view.
|
|
93
19
|
///
|
|
94
|
-
|
|
20
|
+
access(all) struct Display {
|
|
95
21
|
|
|
96
22
|
/// The name of the object.
|
|
97
23
|
///
|
|
98
24
|
/// This field will be displayed in lists and therefore should
|
|
99
25
|
/// be short an concise.
|
|
100
26
|
///
|
|
101
|
-
|
|
27
|
+
access(all) let name: String
|
|
102
28
|
|
|
103
29
|
/// A written description of the object.
|
|
104
30
|
///
|
|
105
31
|
/// This field will be displayed in a detailed view of the object,
|
|
106
32
|
/// so can be more verbose (e.g. a paragraph instead of a single line).
|
|
107
33
|
///
|
|
108
|
-
|
|
34
|
+
access(all) let description: String
|
|
109
35
|
|
|
110
36
|
/// A small thumbnail representation of the object.
|
|
111
37
|
///
|
|
112
38
|
/// This field should be a web-friendly file (i.e JPEG, PNG)
|
|
113
39
|
/// that can be displayed in lists, link previews, etc.
|
|
114
40
|
///
|
|
115
|
-
|
|
41
|
+
access(all) let thumbnail: {File}
|
|
116
42
|
|
|
117
|
-
init(
|
|
43
|
+
view init(
|
|
118
44
|
name: String,
|
|
119
45
|
description: String,
|
|
120
|
-
thumbnail:
|
|
46
|
+
thumbnail: {File}
|
|
121
47
|
) {
|
|
122
48
|
self.name = name
|
|
123
49
|
self.description = description
|
|
@@ -130,7 +56,7 @@ pub contract MetadataViews {
|
|
|
130
56
|
/// @param viewResolver: A reference to the resolver resource
|
|
131
57
|
/// @return An optional Display struct
|
|
132
58
|
///
|
|
133
|
-
|
|
59
|
+
access(all) fun getDisplay(_ viewResolver: &{ViewResolver.Resolver}) : Display? {
|
|
134
60
|
if let view = viewResolver.resolveView(Type<Display>()) {
|
|
135
61
|
if let v = view as? Display {
|
|
136
62
|
return v
|
|
@@ -142,20 +68,20 @@ pub contract MetadataViews {
|
|
|
142
68
|
/// Generic interface that represents a file stored on or off chain. Files
|
|
143
69
|
/// can be used to references images, videos and other media.
|
|
144
70
|
///
|
|
145
|
-
|
|
146
|
-
|
|
71
|
+
access(all) struct interface File {
|
|
72
|
+
access(all) view fun uri(): String
|
|
147
73
|
}
|
|
148
74
|
|
|
149
75
|
/// View to expose a file that is accessible at an HTTP (or HTTPS) URL.
|
|
150
76
|
///
|
|
151
|
-
|
|
152
|
-
|
|
77
|
+
access(all) struct HTTPFile: File {
|
|
78
|
+
access(all) let url: String
|
|
153
79
|
|
|
154
|
-
init(url: String) {
|
|
80
|
+
view init(url: String) {
|
|
155
81
|
self.url = url
|
|
156
82
|
}
|
|
157
83
|
|
|
158
|
-
|
|
84
|
+
access(all) view fun uri(): String {
|
|
159
85
|
return self.url
|
|
160
86
|
}
|
|
161
87
|
}
|
|
@@ -165,13 +91,13 @@ pub contract MetadataViews {
|
|
|
165
91
|
/// rather than a direct URI. A client application can use this CID
|
|
166
92
|
/// to find and load the image via an IPFS gateway.
|
|
167
93
|
///
|
|
168
|
-
|
|
94
|
+
access(all) struct IPFSFile: File {
|
|
169
95
|
|
|
170
96
|
/// CID is the content identifier for this IPFS file.
|
|
171
97
|
///
|
|
172
98
|
/// Ref: https://docs.ipfs.io/concepts/content-addressing/
|
|
173
99
|
///
|
|
174
|
-
|
|
100
|
+
access(all) let cid: String
|
|
175
101
|
|
|
176
102
|
/// Path is an optional path to the file resource in an IPFS directory.
|
|
177
103
|
///
|
|
@@ -179,9 +105,9 @@ pub contract MetadataViews {
|
|
|
179
105
|
///
|
|
180
106
|
/// Ref: https://docs.ipfs.io/concepts/file-systems/
|
|
181
107
|
///
|
|
182
|
-
|
|
108
|
+
access(all) let path: String?
|
|
183
109
|
|
|
184
|
-
init(cid: String, path: String?) {
|
|
110
|
+
view init(cid: String, path: String?) {
|
|
185
111
|
self.cid = cid
|
|
186
112
|
self.path = path
|
|
187
113
|
}
|
|
@@ -191,7 +117,7 @@ pub contract MetadataViews {
|
|
|
191
117
|
///
|
|
192
118
|
/// @return The string containing the file uri
|
|
193
119
|
///
|
|
194
|
-
|
|
120
|
+
access(all) view fun uri(): String {
|
|
195
121
|
if let path = self.path {
|
|
196
122
|
return "ipfs://".concat(self.cid).concat("/").concat(path)
|
|
197
123
|
}
|
|
@@ -200,89 +126,97 @@ pub contract MetadataViews {
|
|
|
200
126
|
}
|
|
201
127
|
}
|
|
202
128
|
|
|
203
|
-
///
|
|
204
|
-
/// with the same or similar metadata, for example an X of 100 set. This
|
|
205
|
-
/// information is useful for wallets and marketplaces.
|
|
206
|
-
/// An NFT might be part of multiple editions, which is why the edition
|
|
207
|
-
/// information is returned as an arbitrary sized array
|
|
129
|
+
/// View to represent a file with an correspoiding mediaType.
|
|
208
130
|
///
|
|
209
|
-
|
|
131
|
+
access(all) struct Media {
|
|
210
132
|
|
|
211
|
-
///
|
|
212
|
-
///
|
|
213
|
-
|
|
214
|
-
pub let name: String?
|
|
215
|
-
|
|
216
|
-
/// The edition number of the object.
|
|
217
|
-
/// For an "24 of 100 (#24/100)" item, the number is 24.
|
|
218
|
-
pub let number: UInt64
|
|
133
|
+
/// File for the media
|
|
134
|
+
///
|
|
135
|
+
access(all) let file: {File}
|
|
219
136
|
|
|
220
|
-
///
|
|
221
|
-
///
|
|
222
|
-
/// For an "24 of 100 (#24/100)" item, max is 100.
|
|
223
|
-
/// For an item with unlimited edition, max should be set to nil.
|
|
137
|
+
/// media-type comes on the form of type/subtype as described here
|
|
138
|
+
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
|
|
224
139
|
///
|
|
225
|
-
|
|
140
|
+
access(all) let mediaType: String
|
|
226
141
|
|
|
227
|
-
init(
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
self.name = name
|
|
232
|
-
self.number = number
|
|
233
|
-
self.max = max
|
|
142
|
+
view init(file: {File}, mediaType: String) {
|
|
143
|
+
self.file=file
|
|
144
|
+
self.mediaType=mediaType
|
|
234
145
|
}
|
|
235
146
|
}
|
|
236
147
|
|
|
237
|
-
/// Wrapper view for multiple
|
|
148
|
+
/// Wrapper view for multiple media views
|
|
238
149
|
///
|
|
239
|
-
|
|
150
|
+
access(all) struct Medias {
|
|
240
151
|
|
|
241
|
-
/// An arbitrary-sized list for any number of
|
|
242
|
-
|
|
243
|
-
pub let infoList: [Edition]
|
|
152
|
+
/// An arbitrary-sized list for any number of Media items
|
|
153
|
+
access(all) let items: [Media]
|
|
244
154
|
|
|
245
|
-
init(_
|
|
246
|
-
self.
|
|
155
|
+
view init(_ items: [Media]) {
|
|
156
|
+
self.items = items
|
|
247
157
|
}
|
|
248
158
|
}
|
|
249
159
|
|
|
250
|
-
/// Helper to get
|
|
160
|
+
/// Helper to get Medias in a typesafe way
|
|
251
161
|
///
|
|
252
162
|
/// @param viewResolver: A reference to the resolver resource
|
|
253
|
-
/// @return
|
|
163
|
+
/// @return A optional Medias struct
|
|
254
164
|
///
|
|
255
|
-
|
|
256
|
-
if let view = viewResolver.resolveView(Type<
|
|
257
|
-
if let v = view as?
|
|
165
|
+
access(all) fun getMedias(_ viewResolver: &{ViewResolver.Resolver}) : Medias? {
|
|
166
|
+
if let view = viewResolver.resolveView(Type<Medias>()) {
|
|
167
|
+
if let v = view as? Medias {
|
|
258
168
|
return v
|
|
259
169
|
}
|
|
260
170
|
}
|
|
261
171
|
return nil
|
|
262
172
|
}
|
|
263
173
|
|
|
264
|
-
/// View
|
|
265
|
-
///
|
|
266
|
-
/// Some may use the NFTs regular ID and some may use a different
|
|
267
|
-
/// classification system. The serial number is expected to be unique among
|
|
268
|
-
/// other NFTs within that project
|
|
174
|
+
/// View to represent a license according to https://spdx.org/licenses/
|
|
175
|
+
/// This view can be used if the content of an NFT is licensed.
|
|
269
176
|
///
|
|
270
|
-
|
|
271
|
-
|
|
177
|
+
access(all) struct License {
|
|
178
|
+
access(all) let spdxIdentifier: String
|
|
272
179
|
|
|
273
|
-
init(_
|
|
274
|
-
self.
|
|
180
|
+
view init(_ identifier: String) {
|
|
181
|
+
self.spdxIdentifier = identifier
|
|
275
182
|
}
|
|
276
183
|
}
|
|
277
184
|
|
|
278
|
-
/// Helper to get
|
|
185
|
+
/// Helper to get License in a typesafe way
|
|
279
186
|
///
|
|
280
187
|
/// @param viewResolver: A reference to the resolver resource
|
|
281
|
-
/// @return
|
|
188
|
+
/// @return A optional License struct
|
|
282
189
|
///
|
|
283
|
-
|
|
284
|
-
if let view = viewResolver.resolveView(Type<
|
|
285
|
-
if let v = view as?
|
|
190
|
+
access(all) fun getLicense(_ viewResolver: &{ViewResolver.Resolver}) : License? {
|
|
191
|
+
if let view = viewResolver.resolveView(Type<License>()) {
|
|
192
|
+
if let v = view as? License {
|
|
193
|
+
return v
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return nil
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/// View to expose a URL to this item on an external site.
|
|
200
|
+
/// This can be used by applications like .find and Blocto to direct users
|
|
201
|
+
/// to the original link for an NFT or a project page that describes the NFT collection.
|
|
202
|
+
/// eg https://www.my-nft-project.com/overview-of-nft-collection
|
|
203
|
+
///
|
|
204
|
+
access(all) struct ExternalURL {
|
|
205
|
+
access(all) let url: String
|
|
206
|
+
|
|
207
|
+
view init(_ url: String) {
|
|
208
|
+
self.url=url
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/// Helper to get ExternalURL in a typesafe way
|
|
213
|
+
///
|
|
214
|
+
/// @param viewResolver: A reference to the resolver resource
|
|
215
|
+
/// @return A optional ExternalURL struct
|
|
216
|
+
///
|
|
217
|
+
access(all) fun getExternalURL(_ viewResolver: &{ViewResolver.Resolver}) : ExternalURL? {
|
|
218
|
+
if let view = viewResolver.resolveView(Type<ExternalURL>()) {
|
|
219
|
+
if let v = view as? ExternalURL {
|
|
286
220
|
return v
|
|
287
221
|
}
|
|
288
222
|
}
|
|
@@ -292,7 +226,7 @@ pub contract MetadataViews {
|
|
|
292
226
|
/// View that defines the composable royalty standard that gives marketplaces a
|
|
293
227
|
/// unified interface to support NFT royalties.
|
|
294
228
|
///
|
|
295
|
-
|
|
229
|
+
access(all) struct Royalty {
|
|
296
230
|
|
|
297
231
|
/// Generic FungibleToken Receiver for the beneficiary of the royalty
|
|
298
232
|
/// Can get the concrete type of the receiver with receiver.getType()
|
|
@@ -300,7 +234,7 @@ pub contract MetadataViews {
|
|
|
300
234
|
/// receiver for this using `getRoyaltyReceiverPublicPath()`, and not
|
|
301
235
|
/// use the default FlowToken receiver. This will allow users to update
|
|
302
236
|
/// the capability in the future to use a more generic capability
|
|
303
|
-
|
|
237
|
+
access(all) let receiver: Capability<&{FungibleToken.Receiver}>
|
|
304
238
|
|
|
305
239
|
/// Multiplier used to calculate the amount of sale value transferred to
|
|
306
240
|
/// royalty receiver. Note - It should be between 0.0 and 1.0
|
|
@@ -311,14 +245,14 @@ pub contract MetadataViews {
|
|
|
311
245
|
/// that already supports the basis points use case because its
|
|
312
246
|
/// operations are entirely deterministic integer operations and support
|
|
313
247
|
/// up to 8 points of precision.
|
|
314
|
-
|
|
248
|
+
access(all) let cut: UFix64
|
|
315
249
|
|
|
316
250
|
/// Optional description: This can be the cause of paying the royalty,
|
|
317
251
|
/// the relationship between the `wallet` and the NFT, or anything else
|
|
318
252
|
/// that the owner might want to specify.
|
|
319
|
-
|
|
253
|
+
access(all) let description: String
|
|
320
254
|
|
|
321
|
-
init(receiver: Capability<&
|
|
255
|
+
view init(receiver: Capability<&{FungibleToken.Receiver}>, cut: UFix64, description: String) {
|
|
322
256
|
pre {
|
|
323
257
|
cut >= 0.0 && cut <= 1.0 : "Cut value should be in valid range i.e [0,1]"
|
|
324
258
|
}
|
|
@@ -332,12 +266,12 @@ pub contract MetadataViews {
|
|
|
332
266
|
/// Marketplaces can query this `Royalties` struct from NFTs
|
|
333
267
|
/// and are expected to pay royalties based on these specifications.
|
|
334
268
|
///
|
|
335
|
-
|
|
269
|
+
access(all) struct Royalties {
|
|
336
270
|
|
|
337
271
|
/// Array that tracks the individual royalties
|
|
338
272
|
access(self) let cutInfos: [Royalty]
|
|
339
273
|
|
|
340
|
-
|
|
274
|
+
access(all) view init(_ cutInfos: [Royalty]) {
|
|
341
275
|
// Validate that sum of all cut multipliers should not be greater than 1.0
|
|
342
276
|
var totalCut = 0.0
|
|
343
277
|
for royalty in cutInfos {
|
|
@@ -352,7 +286,7 @@ pub contract MetadataViews {
|
|
|
352
286
|
///
|
|
353
287
|
/// @return An array containing all the royalties structs
|
|
354
288
|
///
|
|
355
|
-
|
|
289
|
+
access(all) view fun getRoyalties(): [Royalty] {
|
|
356
290
|
return self.cutInfos
|
|
357
291
|
}
|
|
358
292
|
}
|
|
@@ -362,7 +296,7 @@ pub contract MetadataViews {
|
|
|
362
296
|
/// @param viewResolver: A reference to the resolver resource
|
|
363
297
|
/// @return A optional Royalties struct
|
|
364
298
|
///
|
|
365
|
-
|
|
299
|
+
access(all) fun getRoyalties(_ viewResolver: &{ViewResolver.Resolver}) : Royalties? {
|
|
366
300
|
if let view = viewResolver.resolveView(Type<Royalties>()) {
|
|
367
301
|
if let v = view as? Royalties {
|
|
368
302
|
return v
|
|
@@ -377,155 +311,334 @@ pub contract MetadataViews {
|
|
|
377
311
|
///
|
|
378
312
|
/// @return The PublicPath for the generic FT receiver
|
|
379
313
|
///
|
|
380
|
-
|
|
314
|
+
access(all) view fun getRoyaltyReceiverPublicPath(): PublicPath {
|
|
381
315
|
return /public/GenericFTReceiver
|
|
382
316
|
}
|
|
383
317
|
|
|
384
|
-
/// View to represent
|
|
318
|
+
/// View to represent a single field of metadata on an NFT.
|
|
319
|
+
/// This is used to get traits of individual key/value pairs along with some
|
|
320
|
+
/// contextualized data about the trait
|
|
385
321
|
///
|
|
386
|
-
|
|
322
|
+
access(all) struct Trait {
|
|
323
|
+
// The name of the trait. Like Background, Eyes, Hair, etc.
|
|
324
|
+
access(all) let name: String
|
|
387
325
|
|
|
388
|
-
|
|
326
|
+
// The underlying value of the trait, the rest of the fields of a trait provide context to the value.
|
|
327
|
+
access(all) let value: AnyStruct
|
|
328
|
+
|
|
329
|
+
// displayType is used to show some context about what this name and value represent
|
|
330
|
+
// for instance, you could set value to a unix timestamp, and specify displayType as "Date" to tell
|
|
331
|
+
// platforms to consume this trait as a date and not a number
|
|
332
|
+
access(all) let displayType: String?
|
|
333
|
+
|
|
334
|
+
// Rarity can also be used directly on an attribute.
|
|
335
|
+
//
|
|
336
|
+
// This is optional because not all attributes need to contribute to the NFT's rarity.
|
|
337
|
+
access(all) let rarity: Rarity?
|
|
338
|
+
|
|
339
|
+
view init(name: String, value: AnyStruct, displayType: String?, rarity: Rarity?) {
|
|
340
|
+
self.name = name
|
|
341
|
+
self.value = value
|
|
342
|
+
self.displayType = displayType
|
|
343
|
+
self.rarity = rarity
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/// Wrapper view to return all the traits on an NFT.
|
|
348
|
+
/// This is used to return traits as individual key/value pairs along with
|
|
349
|
+
/// some contextualized data about each trait.
|
|
350
|
+
access(all) struct Traits {
|
|
351
|
+
access(all) let traits: [Trait]
|
|
352
|
+
|
|
353
|
+
view init(_ traits: [Trait]) {
|
|
354
|
+
self.traits = traits
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/// Adds a single Trait to the Traits view
|
|
358
|
+
///
|
|
359
|
+
/// @param Trait: The trait struct to be added
|
|
389
360
|
///
|
|
390
|
-
|
|
361
|
+
access(all) fun addTrait(_ t: Trait) {
|
|
362
|
+
self.traits.append(t)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
391
365
|
|
|
392
|
-
|
|
393
|
-
|
|
366
|
+
/// Helper to get Traits view in a typesafe way
|
|
367
|
+
///
|
|
368
|
+
/// @param viewResolver: A reference to the resolver resource
|
|
369
|
+
/// @return A optional Traits struct
|
|
370
|
+
///
|
|
371
|
+
access(all) fun getTraits(_ viewResolver: &{ViewResolver.Resolver}) : Traits? {
|
|
372
|
+
if let view = viewResolver.resolveView(Type<Traits>()) {
|
|
373
|
+
if let v = view as? Traits {
|
|
374
|
+
return v
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return nil
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/// Helper function to easily convert a dictionary to traits. For NFT
|
|
381
|
+
/// collections that do not need either of the optional values of a Trait,
|
|
382
|
+
/// this method should suffice to give them an array of valid traits.
|
|
383
|
+
///
|
|
384
|
+
/// @param dict: The dictionary to be converted to Traits
|
|
385
|
+
/// @param excludedNames: An optional String array specifying the `dict`
|
|
386
|
+
/// keys that are not wanted to become `Traits`
|
|
387
|
+
/// @return The generated Traits view
|
|
388
|
+
///
|
|
389
|
+
access(all) fun dictToTraits(dict: {String: AnyStruct}, excludedNames: [String]?): Traits {
|
|
390
|
+
// Collection owners might not want all the fields in their metadata included.
|
|
391
|
+
// They might want to handle some specially, or they might just not want them included at all.
|
|
392
|
+
if excludedNames != nil {
|
|
393
|
+
for k in excludedNames! {
|
|
394
|
+
dict.remove(key: k)
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
let traits: [Trait] = []
|
|
399
|
+
for k in dict.keys {
|
|
400
|
+
let trait = Trait(name: k, value: dict[k]!, displayType: nil, rarity: nil)
|
|
401
|
+
traits.append(trait)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return Traits(traits)
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/// Optional view for collections that issue multiple objects
|
|
408
|
+
/// with the same or similar metadata, for example an X of 100 set. This
|
|
409
|
+
/// information is useful for wallets and marketplaces.
|
|
410
|
+
/// An NFT might be part of multiple editions, which is why the edition
|
|
411
|
+
/// information is returned as an arbitrary sized array
|
|
412
|
+
///
|
|
413
|
+
access(all) struct Edition {
|
|
414
|
+
|
|
415
|
+
/// The name of the edition
|
|
416
|
+
/// For example, this could be Set, Play, Series,
|
|
417
|
+
/// or any other way a project could classify its editions
|
|
418
|
+
access(all) let name: String?
|
|
419
|
+
|
|
420
|
+
/// The edition number of the object.
|
|
421
|
+
/// For an "24 of 100 (#24/100)" item, the number is 24.
|
|
422
|
+
access(all) let number: UInt64
|
|
423
|
+
|
|
424
|
+
/// The max edition number of this type of objects.
|
|
425
|
+
/// This field should only be provided for limited-editioned objects.
|
|
426
|
+
/// For an "24 of 100 (#24/100)" item, max is 100.
|
|
427
|
+
/// For an item with unlimited edition, max should be set to nil.
|
|
394
428
|
///
|
|
395
|
-
|
|
429
|
+
access(all) let max: UInt64?
|
|
396
430
|
|
|
397
|
-
init(
|
|
398
|
-
|
|
399
|
-
|
|
431
|
+
view init(name: String?, number: UInt64, max: UInt64?) {
|
|
432
|
+
if max != nil {
|
|
433
|
+
assert(number <= max!, message: "The number cannot be greater than the max number!")
|
|
434
|
+
}
|
|
435
|
+
self.name = name
|
|
436
|
+
self.number = number
|
|
437
|
+
self.max = max
|
|
400
438
|
}
|
|
401
439
|
}
|
|
402
440
|
|
|
403
|
-
/// Wrapper view for multiple
|
|
441
|
+
/// Wrapper view for multiple Edition views
|
|
404
442
|
///
|
|
405
|
-
|
|
443
|
+
access(all) struct Editions {
|
|
406
444
|
|
|
407
|
-
/// An arbitrary-sized list for any number of
|
|
408
|
-
|
|
445
|
+
/// An arbitrary-sized list for any number of editions
|
|
446
|
+
/// that the NFT might be a part of
|
|
447
|
+
access(all) let infoList: [Edition]
|
|
409
448
|
|
|
410
|
-
init(_
|
|
411
|
-
self.
|
|
449
|
+
view init(_ infoList: [Edition]) {
|
|
450
|
+
self.infoList = infoList
|
|
412
451
|
}
|
|
413
452
|
}
|
|
414
453
|
|
|
415
|
-
/// Helper to get
|
|
454
|
+
/// Helper to get Editions in a typesafe way
|
|
416
455
|
///
|
|
417
456
|
/// @param viewResolver: A reference to the resolver resource
|
|
418
|
-
/// @return
|
|
457
|
+
/// @return An optional Editions struct
|
|
419
458
|
///
|
|
420
|
-
|
|
421
|
-
if let view = viewResolver.resolveView(Type<
|
|
422
|
-
if let v = view as?
|
|
459
|
+
access(all) fun getEditions(_ viewResolver: &{ViewResolver.Resolver}) : Editions? {
|
|
460
|
+
if let view = viewResolver.resolveView(Type<Editions>()) {
|
|
461
|
+
if let v = view as? Editions {
|
|
423
462
|
return v
|
|
424
463
|
}
|
|
425
464
|
}
|
|
426
465
|
return nil
|
|
427
466
|
}
|
|
428
467
|
|
|
429
|
-
/// View
|
|
430
|
-
///
|
|
468
|
+
/// View representing a project-defined serial number for a specific NFT
|
|
469
|
+
/// Projects have different definitions for what a serial number should be
|
|
470
|
+
/// Some may use the NFTs regular ID and some may use a different
|
|
471
|
+
/// classification system. The serial number is expected to be unique among
|
|
472
|
+
/// other NFTs within that project
|
|
431
473
|
///
|
|
432
|
-
|
|
433
|
-
|
|
474
|
+
access(all) struct Serial {
|
|
475
|
+
access(all) let number: UInt64
|
|
434
476
|
|
|
435
|
-
init(_
|
|
436
|
-
self.
|
|
477
|
+
view init(_ number: UInt64) {
|
|
478
|
+
self.number = number
|
|
437
479
|
}
|
|
438
480
|
}
|
|
439
481
|
|
|
440
|
-
/// Helper to get
|
|
482
|
+
/// Helper to get Serial in a typesafe way
|
|
441
483
|
///
|
|
442
484
|
/// @param viewResolver: A reference to the resolver resource
|
|
443
|
-
/// @return
|
|
485
|
+
/// @return An optional Serial struct
|
|
444
486
|
///
|
|
445
|
-
|
|
446
|
-
if let view = viewResolver.resolveView(Type<
|
|
447
|
-
if let v = view as?
|
|
487
|
+
access(all) fun getSerial(_ viewResolver: &{ViewResolver.Resolver}) : Serial? {
|
|
488
|
+
if let view = viewResolver.resolveView(Type<Serial>()) {
|
|
489
|
+
if let v = view as? Serial {
|
|
448
490
|
return v
|
|
449
491
|
}
|
|
450
492
|
}
|
|
451
493
|
return nil
|
|
452
494
|
}
|
|
453
495
|
|
|
454
|
-
/// View to expose
|
|
455
|
-
///
|
|
456
|
-
///
|
|
457
|
-
/// eg https://www.my-nft-project.com/overview-of-nft-collection
|
|
496
|
+
/// View to expose rarity information for a single rarity
|
|
497
|
+
/// Note that a rarity needs to have either score or description but it can
|
|
498
|
+
/// have both
|
|
458
499
|
///
|
|
459
|
-
|
|
460
|
-
|
|
500
|
+
access(all) struct Rarity {
|
|
501
|
+
/// The score of the rarity as a number
|
|
502
|
+
access(all) let score: UFix64?
|
|
461
503
|
|
|
462
|
-
|
|
463
|
-
|
|
504
|
+
/// The maximum value of score
|
|
505
|
+
access(all) let max: UFix64?
|
|
506
|
+
|
|
507
|
+
/// The description of the rarity as a string.
|
|
508
|
+
///
|
|
509
|
+
/// This could be Legendary, Epic, Rare, Uncommon, Common or any other string value
|
|
510
|
+
access(all) let description: String?
|
|
511
|
+
|
|
512
|
+
view init(score: UFix64?, max: UFix64?, description: String?) {
|
|
513
|
+
if score == nil && description == nil {
|
|
514
|
+
panic("A Rarity needs to set score, description or both")
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
self.score = score
|
|
518
|
+
self.max = max
|
|
519
|
+
self.description = description
|
|
464
520
|
}
|
|
465
521
|
}
|
|
466
522
|
|
|
467
|
-
/// Helper to get
|
|
523
|
+
/// Helper to get Rarity view in a typesafe way
|
|
468
524
|
///
|
|
469
525
|
/// @param viewResolver: A reference to the resolver resource
|
|
470
|
-
/// @return A optional
|
|
526
|
+
/// @return A optional Rarity struct
|
|
471
527
|
///
|
|
472
|
-
|
|
473
|
-
if let view = viewResolver.resolveView(Type<
|
|
474
|
-
if let v = view as?
|
|
528
|
+
access(all) fun getRarity(_ viewResolver: &{ViewResolver.Resolver}) : Rarity? {
|
|
529
|
+
if let view = viewResolver.resolveView(Type<Rarity>()) {
|
|
530
|
+
if let v = view as? Rarity {
|
|
475
531
|
return v
|
|
476
532
|
}
|
|
477
533
|
}
|
|
478
534
|
return nil
|
|
479
535
|
}
|
|
480
536
|
|
|
537
|
+
/// NFTView wraps all Core views along `id` and `uuid` fields, and is used
|
|
538
|
+
/// to give a complete picture of an NFT. Most NFTs should implement this
|
|
539
|
+
/// view.
|
|
540
|
+
///
|
|
541
|
+
access(all) struct NFTView {
|
|
542
|
+
access(all) let id: UInt64
|
|
543
|
+
access(all) let uuid: UInt64
|
|
544
|
+
access(all) let display: MetadataViews.Display?
|
|
545
|
+
access(all) let externalURL: MetadataViews.ExternalURL?
|
|
546
|
+
access(all) let collectionData: NFTCollectionData?
|
|
547
|
+
access(all) let collectionDisplay: NFTCollectionDisplay?
|
|
548
|
+
access(all) let royalties: Royalties?
|
|
549
|
+
access(all) let traits: Traits?
|
|
550
|
+
|
|
551
|
+
view init(
|
|
552
|
+
id : UInt64,
|
|
553
|
+
uuid : UInt64,
|
|
554
|
+
display : MetadataViews.Display?,
|
|
555
|
+
externalURL : MetadataViews.ExternalURL?,
|
|
556
|
+
collectionData : NFTCollectionData?,
|
|
557
|
+
collectionDisplay : NFTCollectionDisplay?,
|
|
558
|
+
royalties : Royalties?,
|
|
559
|
+
traits: Traits?
|
|
560
|
+
) {
|
|
561
|
+
self.id = id
|
|
562
|
+
self.uuid = uuid
|
|
563
|
+
self.display = display
|
|
564
|
+
self.externalURL = externalURL
|
|
565
|
+
self.collectionData = collectionData
|
|
566
|
+
self.collectionDisplay = collectionDisplay
|
|
567
|
+
self.royalties = royalties
|
|
568
|
+
self.traits = traits
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/// Helper to get an NFT view
|
|
573
|
+
///
|
|
574
|
+
/// @param id: The NFT id
|
|
575
|
+
/// @param viewResolver: A reference to the resolver resource
|
|
576
|
+
/// @return A NFTView struct
|
|
577
|
+
///
|
|
578
|
+
access(all) fun getNFTView(id: UInt64, viewResolver: &{ViewResolver.Resolver}) : NFTView {
|
|
579
|
+
let nftView = viewResolver.resolveView(Type<NFTView>())
|
|
580
|
+
if nftView != nil {
|
|
581
|
+
return nftView! as! NFTView
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return NFTView(
|
|
585
|
+
id : id,
|
|
586
|
+
uuid: viewResolver.uuid,
|
|
587
|
+
display: MetadataViews.getDisplay(viewResolver),
|
|
588
|
+
externalURL : MetadataViews.getExternalURL(viewResolver),
|
|
589
|
+
collectionData : self.getNFTCollectionData(viewResolver),
|
|
590
|
+
collectionDisplay : self.getNFTCollectionDisplay(viewResolver),
|
|
591
|
+
royalties : self.getRoyalties(viewResolver),
|
|
592
|
+
traits : self.getTraits(viewResolver)
|
|
593
|
+
)
|
|
594
|
+
}
|
|
595
|
+
|
|
481
596
|
/// View to expose the information needed store and retrieve an NFT.
|
|
482
597
|
/// This can be used by applications to setup a NFT collection with proper
|
|
483
598
|
/// storage and public capabilities.
|
|
484
599
|
///
|
|
485
|
-
|
|
600
|
+
access(all) struct NFTCollectionData {
|
|
486
601
|
/// Path in storage where this NFT is recommended to be stored.
|
|
487
|
-
|
|
602
|
+
access(all) let storagePath: StoragePath
|
|
488
603
|
|
|
489
604
|
/// Public path which must be linked to expose public capabilities of this NFT
|
|
490
605
|
/// including standard NFT interfaces and metadataviews interfaces
|
|
491
|
-
|
|
606
|
+
access(all) let publicPath: PublicPath
|
|
492
607
|
|
|
493
608
|
/// Private path which should be linked to expose the provider
|
|
494
609
|
/// capability to withdraw NFTs from the collection holding NFTs
|
|
495
|
-
|
|
610
|
+
access(all) let providerPath: PrivatePath
|
|
496
611
|
|
|
497
612
|
/// Public collection type that is expected to provide sufficient read-only access to standard
|
|
498
|
-
/// functions (deposit + getIDs + borrowNFT)
|
|
499
|
-
/// This field is for backwards compatibility with collections that have not used the standard
|
|
500
|
-
/// NonFungibleToken.CollectionPublic interface when setting up collections. For new
|
|
613
|
+
/// functions (deposit + getIDs + borrowNFT). For new
|
|
501
614
|
/// collections, this may be set to be equal to the type specified in `publicLinkedType`.
|
|
502
|
-
|
|
615
|
+
access(all) let publicCollection: Type
|
|
503
616
|
|
|
504
617
|
/// Type that should be linked at the aforementioned public path. This is normally a
|
|
505
|
-
/// restricted type with many interfaces. Notably the
|
|
506
|
-
/// `NFT.Receiver`, and `
|
|
507
|
-
|
|
618
|
+
/// restricted type with many interfaces. Notably the
|
|
619
|
+
/// `NFT.Receiver`, and `ViewResolver.ResolverCollection` interfaces are required.
|
|
620
|
+
access(all) let publicLinkedType: Type
|
|
508
621
|
|
|
509
622
|
/// Type that should be linked at the aforementioned private path. This is normally
|
|
510
623
|
/// a restricted type with at a minimum the `NFT.Provider` interface
|
|
511
|
-
|
|
624
|
+
access(all) let providerLinkedType: Type
|
|
512
625
|
|
|
513
626
|
/// Function that allows creation of an empty NFT collection that is intended to store
|
|
514
627
|
/// this NFT.
|
|
515
|
-
|
|
628
|
+
access(all) let createEmptyCollection: fun(): @{NonFungibleToken.Collection}
|
|
516
629
|
|
|
517
|
-
init(
|
|
630
|
+
view init(
|
|
518
631
|
storagePath: StoragePath,
|
|
519
632
|
publicPath: PublicPath,
|
|
520
633
|
providerPath: PrivatePath,
|
|
521
634
|
publicCollection: Type,
|
|
522
635
|
publicLinkedType: Type,
|
|
523
636
|
providerLinkedType: Type,
|
|
524
|
-
createEmptyCollectionFunction: (
|
|
637
|
+
createEmptyCollectionFunction: fun(): @{NonFungibleToken.Collection}
|
|
525
638
|
) {
|
|
526
639
|
pre {
|
|
527
|
-
publicLinkedType.isSubtype(of: Type<&{NonFungibleToken.
|
|
528
|
-
providerLinkedType.isSubtype(of: Type<&{NonFungibleToken.Provider,
|
|
640
|
+
publicLinkedType.isSubtype(of: Type<&{NonFungibleToken.Receiver, ViewResolver.ResolverCollection}>()): "Public type must include NonFungibleToken.Receiver and ViewResolver.ResolverCollection interfaces."
|
|
641
|
+
providerLinkedType.isSubtype(of: Type<&{NonFungibleToken.Provider, ViewResolver.ResolverCollection}>()): "Provider type must include NonFungibleToken.Provider and ViewResolver.ResolverCollection interface."
|
|
529
642
|
}
|
|
530
643
|
self.storagePath=storagePath
|
|
531
644
|
self.publicPath=publicPath
|
|
@@ -542,7 +655,7 @@ pub contract MetadataViews {
|
|
|
542
655
|
/// @param viewResolver: A reference to the resolver resource
|
|
543
656
|
/// @return A optional NFTCollectionData struct
|
|
544
657
|
///
|
|
545
|
-
|
|
658
|
+
access(all) fun getNFTCollectionData(_ viewResolver: &{ViewResolver.Resolver}) : NFTCollectionData? {
|
|
546
659
|
if let view = viewResolver.resolveView(Type<NFTCollectionData>()) {
|
|
547
660
|
if let v = view as? NFTCollectionData {
|
|
548
661
|
return v
|
|
@@ -555,33 +668,33 @@ pub contract MetadataViews {
|
|
|
555
668
|
/// collection. This can be used by applications to give an overview and
|
|
556
669
|
/// graphics of the NFT collection this NFT belongs to.
|
|
557
670
|
///
|
|
558
|
-
|
|
671
|
+
access(all) struct NFTCollectionDisplay {
|
|
559
672
|
// Name that should be used when displaying this NFT collection.
|
|
560
|
-
|
|
673
|
+
access(all) let name: String
|
|
561
674
|
|
|
562
675
|
// Description that should be used to give an overview of this collection.
|
|
563
|
-
|
|
676
|
+
access(all) let description: String
|
|
564
677
|
|
|
565
678
|
// External link to a URL to view more information about this collection.
|
|
566
|
-
|
|
679
|
+
access(all) let externalURL: MetadataViews.ExternalURL
|
|
567
680
|
|
|
568
681
|
// Square-sized image to represent this collection.
|
|
569
|
-
|
|
682
|
+
access(all) let squareImage: MetadataViews.Media
|
|
570
683
|
|
|
571
684
|
// Banner-sized image for this collection, recommended to have a size near 1200x630.
|
|
572
|
-
|
|
685
|
+
access(all) let bannerImage: MetadataViews.Media
|
|
573
686
|
|
|
574
687
|
// Social links to reach this collection's social homepages.
|
|
575
688
|
// Possible keys may be "instagram", "twitter", "discord", etc.
|
|
576
|
-
|
|
689
|
+
access(all) let socials: {String: MetadataViews.ExternalURL}
|
|
577
690
|
|
|
578
|
-
init(
|
|
691
|
+
view init(
|
|
579
692
|
name: String,
|
|
580
693
|
description: String,
|
|
581
|
-
externalURL: ExternalURL,
|
|
582
|
-
squareImage: Media,
|
|
583
|
-
bannerImage: Media,
|
|
584
|
-
socials: {String: ExternalURL}
|
|
694
|
+
externalURL: MetadataViews.ExternalURL,
|
|
695
|
+
squareImage: MetadataViews.Media,
|
|
696
|
+
bannerImage: MetadataViews.Media,
|
|
697
|
+
socials: {String: MetadataViews.ExternalURL}
|
|
585
698
|
) {
|
|
586
699
|
self.name = name
|
|
587
700
|
self.description = description
|
|
@@ -598,7 +711,7 @@ pub contract MetadataViews {
|
|
|
598
711
|
/// @param viewResolver: A reference to the resolver resource
|
|
599
712
|
/// @return A optional NFTCollection struct
|
|
600
713
|
///
|
|
601
|
-
|
|
714
|
+
access(all) fun getNFTCollectionDisplay(_ viewResolver: &{ViewResolver.Resolver}) : NFTCollectionDisplay? {
|
|
602
715
|
if let view = viewResolver.resolveView(Type<NFTCollectionDisplay>()) {
|
|
603
716
|
if let v = view as? NFTCollectionDisplay {
|
|
604
717
|
return v
|
|
@@ -606,135 +719,4 @@ pub contract MetadataViews {
|
|
|
606
719
|
}
|
|
607
720
|
return nil
|
|
608
721
|
}
|
|
609
|
-
|
|
610
|
-
/// View to expose rarity information for a single rarity
|
|
611
|
-
/// Note that a rarity needs to have either score or description but it can
|
|
612
|
-
/// have both
|
|
613
|
-
///
|
|
614
|
-
pub struct Rarity {
|
|
615
|
-
/// The score of the rarity as a number
|
|
616
|
-
pub let score: UFix64?
|
|
617
|
-
|
|
618
|
-
/// The maximum value of score
|
|
619
|
-
pub let max: UFix64?
|
|
620
|
-
|
|
621
|
-
/// The description of the rarity as a string.
|
|
622
|
-
///
|
|
623
|
-
/// This could be Legendary, Epic, Rare, Uncommon, Common or any other string value
|
|
624
|
-
pub let description: String?
|
|
625
|
-
|
|
626
|
-
init(score: UFix64?, max: UFix64?, description: String?) {
|
|
627
|
-
if score == nil && description == nil {
|
|
628
|
-
panic("A Rarity needs to set score, description or both")
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
self.score = score
|
|
632
|
-
self.max = max
|
|
633
|
-
self.description = description
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
/// Helper to get Rarity view in a typesafe way
|
|
638
|
-
///
|
|
639
|
-
/// @param viewResolver: A reference to the resolver resource
|
|
640
|
-
/// @return A optional Rarity struct
|
|
641
|
-
///
|
|
642
|
-
pub fun getRarity(_ viewResolver: &{Resolver}) : Rarity? {
|
|
643
|
-
if let view = viewResolver.resolveView(Type<Rarity>()) {
|
|
644
|
-
if let v = view as? Rarity {
|
|
645
|
-
return v
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
return nil
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
/// View to represent a single field of metadata on an NFT.
|
|
652
|
-
/// This is used to get traits of individual key/value pairs along with some
|
|
653
|
-
/// contextualized data about the trait
|
|
654
|
-
///
|
|
655
|
-
pub struct Trait {
|
|
656
|
-
// The name of the trait. Like Background, Eyes, Hair, etc.
|
|
657
|
-
pub let name: String
|
|
658
|
-
|
|
659
|
-
// The underlying value of the trait, the rest of the fields of a trait provide context to the value.
|
|
660
|
-
pub let value: AnyStruct
|
|
661
|
-
|
|
662
|
-
// displayType is used to show some context about what this name and value represent
|
|
663
|
-
// for instance, you could set value to a unix timestamp, and specify displayType as "Date" to tell
|
|
664
|
-
// platforms to consume this trait as a date and not a number
|
|
665
|
-
pub let displayType: String?
|
|
666
|
-
|
|
667
|
-
// Rarity can also be used directly on an attribute.
|
|
668
|
-
//
|
|
669
|
-
// This is optional because not all attributes need to contribute to the NFT's rarity.
|
|
670
|
-
pub let rarity: Rarity?
|
|
671
|
-
|
|
672
|
-
init(name: String, value: AnyStruct, displayType: String?, rarity: Rarity?) {
|
|
673
|
-
self.name = name
|
|
674
|
-
self.value = value
|
|
675
|
-
self.displayType = displayType
|
|
676
|
-
self.rarity = rarity
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
/// Wrapper view to return all the traits on an NFT.
|
|
681
|
-
/// This is used to return traits as individual key/value pairs along with
|
|
682
|
-
/// some contextualized data about each trait.
|
|
683
|
-
pub struct Traits {
|
|
684
|
-
pub let traits: [Trait]
|
|
685
|
-
|
|
686
|
-
init(_ traits: [Trait]) {
|
|
687
|
-
self.traits = traits
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
/// Adds a single Trait to the Traits view
|
|
691
|
-
///
|
|
692
|
-
/// @param Trait: The trait struct to be added
|
|
693
|
-
///
|
|
694
|
-
pub fun addTrait(_ t: Trait) {
|
|
695
|
-
self.traits.append(t)
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
/// Helper to get Traits view in a typesafe way
|
|
700
|
-
///
|
|
701
|
-
/// @param viewResolver: A reference to the resolver resource
|
|
702
|
-
/// @return A optional Traits struct
|
|
703
|
-
///
|
|
704
|
-
pub fun getTraits(_ viewResolver: &{Resolver}) : Traits? {
|
|
705
|
-
if let view = viewResolver.resolveView(Type<Traits>()) {
|
|
706
|
-
if let v = view as? Traits {
|
|
707
|
-
return v
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
return nil
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
/// Helper function to easily convert a dictionary to traits. For NFT
|
|
714
|
-
/// collections that do not need either of the optional values of a Trait,
|
|
715
|
-
/// this method should suffice to give them an array of valid traits.
|
|
716
|
-
///
|
|
717
|
-
/// @param dict: The dictionary to be converted to Traits
|
|
718
|
-
/// @param excludedNames: An optional String array specifying the `dict`
|
|
719
|
-
/// keys that are not wanted to become `Traits`
|
|
720
|
-
/// @return The generated Traits view
|
|
721
|
-
///
|
|
722
|
-
pub fun dictToTraits(dict: {String: AnyStruct}, excludedNames: [String]?): Traits {
|
|
723
|
-
// Collection owners might not want all the fields in their metadata included.
|
|
724
|
-
// They might want to handle some specially, or they might just not want them included at all.
|
|
725
|
-
if excludedNames != nil {
|
|
726
|
-
for k in excludedNames! {
|
|
727
|
-
dict.remove(key: k)
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
let traits: [Trait] = []
|
|
732
|
-
for k in dict.keys {
|
|
733
|
-
let trait = Trait(name: k, value: dict[k]!, displayType: nil, rarity: nil)
|
|
734
|
-
traits.append(trait)
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
return Traits(traits)
|
|
738
|
-
}
|
|
739
|
-
|
|
740
722
|
}
|