Smart Contract
NTest_Trm_Asset_NFT
A.2a20bcae76f735aa.NTest_Trm_Asset_NFT
1import NonFungibleToken from 0x1d7e57aa55817448
2import ViewResolver from 0x1d7e57aa55817448
3import MetadataViews from 0x1d7e57aa55817448
4
5
6access(all) contract NTest_Trm_Asset_NFT: NonFungibleToken {
7
8 access(all) var totalSupply: UInt64
9 /// Standard Paths
10
11 access(all) let CollectionStoragePath: StoragePath
12 access(all) let CollectionPublicPath: PublicPath
13
14 /// Path where the minter should be stored
15 /// The standard paths for the collection are stored in the collection resource type
16 access(all) let MinterStoragePath: StoragePath
17 access(all) let adminStoragePath: StoragePath
18
19 access(all) event AssetMinted(id: UInt64, title: String, description: String, thumbnail: String, metadata: {String: String}, serialNumber: UInt32, url: String, ownerInfo: String, assetType: String, kID: String, songID: String, masterTokenID: UInt64?, webhookID: String?)
20 access(all) event AssetOwnerTransfer(id: UInt64, ownerFrom: String, ownerTo: String, songID: String, price: UFix64?, priceUnit: String?, paymentRefInfo: String?, webhookID: String?)
21 access(all) event AssetBatchMinted(startID: UInt64, endID: UInt64, totalCount: UInt32, startSerialNumber: UInt32, endSerialNumber: UInt32, title: String, description: String, thumbnail: String, metadata: {String: String}, url: String, ownerInfo: String, assetType: String, kID: String, songID: String, masterTokenID: UInt64, webhookID: String?)
22 access(all) event AssetUpdated(id: UInt64 , title: String?, description: String?, thumbnail: String?, assetType: String?, ownerInfo: String, metadata: {String: String}?, webhookID: String? )
23 access(all) event AssetBatchUpdated(ids: [UInt64] , title: String?, description: String?, thumbnail: String?, assetType: String?, ownerInfo: String, metadata: {String: String}?, webhookID: String? )
24
25
26
27 access(all) resource NFT: NonFungibleToken.NFT {
28 access(all) let id: UInt64
29 access(all) let masterTokenID: UInt64
30
31 access(all) var title: String
32 access(all) var description: String
33 access(all) var thumbnail: String
34
35 access(all) let url: String
36 access(all) var ownerInfo: String
37 access(all) let serialNumber: UInt32
38 access(all) var assetType: String
39 access(all) let kID: String
40 access(all) var songID: String
41
42 access(all) var metadata: {String: AnyStruct}
43
44 init(
45 id: UInt64,
46 title: String,
47 description: String,
48 thumbnail: String,
49 metadata: {String: AnyStruct},
50 serialNumber: UInt32,
51 url: String,
52 ownerInfo: String,
53 assetType: String,
54 kID: String,
55 songID: String,
56 masterTokenID: UInt64
57
58 ) {
59 self.id = id
60 self.title = title
61 self.description = description
62 self.thumbnail = thumbnail
63 self.serialNumber = serialNumber
64 self.url = url
65 self.ownerInfo = ownerInfo
66 self.assetType = assetType
67 self.kID = kID
68 self.songID = songID
69 self.masterTokenID = masterTokenID
70
71
72 self.metadata = metadata
73 }
74
75 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
76 return <-NTest_Trm_Asset_NFT.createEmptyCollection(nftType: Type<@NTest_Trm_Asset_NFT.NFT>())
77 }
78
79 access(all) view fun getViews(): [Type] {
80 return [
81 Type<MetadataViews.Display>(),
82 Type<MetadataViews.ExternalURL>(),
83 Type<MetadataViews.Editions>(),
84 Type<MetadataViews.NFTCollectionData>(),
85 Type<MetadataViews.NFTCollectionDisplay>(),
86 Type<MetadataViews.Serial>()
87 ]
88 }
89
90 access(all) fun resolveView(_ view: Type): AnyStruct? {
91 switch view {
92 case Type<MetadataViews.Display>():
93 return MetadataViews.Display(
94 name: self.title,
95 description: self.description,
96 thumbnail: MetadataViews.HTTPFile(
97 url: self.thumbnail
98 )
99 )
100 case Type<MetadataViews.Editions>():
101 // There is no max number of NFTs that can be minted from this contract
102 // so the max edition field value is set to nil
103 let editionInfo = MetadataViews.Edition(name: "Intertrust NFT Creation", number: self.id, max: nil)
104 let editionList: [MetadataViews.Edition] = [editionInfo]
105 return MetadataViews.Editions(
106 editionList
107 )
108 case Type<MetadataViews.Serial>():
109 return MetadataViews.Serial(
110 self.id
111 )
112 case Type<MetadataViews.ExternalURL>():
113 return MetadataViews.ExternalURL("https://www.intertrust.com/marketmaker/")
114 case Type<MetadataViews.NFTCollectionData>():
115 return NTest_Trm_Asset_NFT.resolveContractView(resourceType: Type<@NTest_Trm_Asset_NFT.NFT>(), viewType: Type<MetadataViews.NFTCollectionData>())
116 case Type<MetadataViews.NFTCollectionDisplay>():
117 return NTest_Trm_Asset_NFT.resolveContractView(resourceType: Type<@NTest_Trm_Asset_NFT.NFT>(), viewType: Type<MetadataViews.NFTCollectionDisplay>())
118 }
119 return nil
120
121 }
122
123 access(contract) fun transferOwner(id: UInt64, ownerFrom: String, ownerTo: String, songID: String, price: UFix64?, priceUnit: String?, paymentRefInfo: String?, webhookID: String?) {
124 if (ownerFrom == self.ownerInfo) {
125 self.ownerInfo = ownerTo
126
127 emit AssetOwnerTransfer(id: id, ownerFrom: ownerFrom, ownerTo: ownerTo, songID: songID, price: price, priceUnit: priceUnit, paymentRefInfo: paymentRefInfo, webhookID: webhookID)
128
129 }
130
131 }
132
133 access(contract) fun updateMetadata(id: UInt64 , title: String?, description: String?, thumbnail: String?, assetType: String?, ownerInfo: String, metadata: {String: String}?, webhookID: String? ){
134 if (ownerInfo == self.ownerInfo) {
135 if let tempname = title {self.title = tempname}
136
137 if let tempdesc = description {self.description = tempdesc}
138
139 if let tempthumbnail = thumbnail {self.thumbnail = tempthumbnail}
140
141 if let tempassetType = assetType {self.assetType = tempassetType}
142
143 if let tempmetadata = metadata {self.metadata = tempmetadata}
144 }
145
146 }
147
148
149
150 }
151
152 access(all) resource Collection: NonFungibleToken.Collection {
153 /// dictionary of NFT conforming tokens
154 /// NFT is a resource type with an `UInt64` ID field
155 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
156
157 init () {
158 self.ownedNFTs <- {}
159 }
160
161 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
162 let supportedTypes: {Type: Bool} = {}
163 supportedTypes[Type<@NTest_Trm_Asset_NFT.NFT>()] = true
164 return supportedTypes
165 }
166
167 /// Returns whether or not the given type is accepted by the collection
168 /// A collection that can accept any type should just return true by default
169 access(all) view fun isSupportedNFTType(type: Type): Bool {
170 return type == Type<@NTest_Trm_Asset_NFT.NFT>()
171 }
172
173 access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
174 let token <- self.ownedNFTs.remove(key: withdrawID)
175 ?? panic("Could not withdraw an NFT with the provided ID from the collection")
176
177 return <-token
178 }
179
180 /// deposit takes a NFT and adds it to the collections dictionary
181 /// and adds the ID to the id array
182 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
183 pre {
184 false: "Depositing Asset directly to Asset contract is not allowed"
185 }
186 let token <- token as! @NTest_Trm_Asset_NFT.NFT
187 let id = token.id
188
189 // add the new token to the dictionary which removes the old one
190 let oldToken <- self.ownedNFTs[token.id] <- token
191
192 destroy oldToken
193 }
194
195 access(all) view fun getIDs(): [UInt64] {
196 return self.ownedNFTs.keys
197 }
198
199 /// Gets the amount of NFTs stored in the collection
200 access(all) view fun getLength(): Int {
201 return self.ownedNFTs.length
202 }
203
204 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
205 return (&self.ownedNFTs[id])
206 }
207
208 /// Borrow the view resolver for the specified NFT ID
209 access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
210 if let nft = &self.ownedNFTs[id] as &{NonFungibleToken.NFT}? {
211 return nft as &{ViewResolver.Resolver}
212 }
213 return nil
214 }
215
216 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
217 return <-NTest_Trm_Asset_NFT.createEmptyCollection(nftType: Type<@NTest_Trm_Asset_NFT.NFT>())
218 }
219
220 access(all) view fun getSerialNumber(id: UInt64): UInt32 {
221 pre {
222 self.ownedNFTs[id] != nil: "Asset Token ID does not exist"
223 }
224
225 let refNFT = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
226 let refAssetNFT: &NTest_Trm_Asset_NFT.NFT = refNFT as! &NFT
227
228 return refAssetNFT.serialNumber
229 }
230 access(all) view fun getownerInfo(id: UInt64): String {
231 pre {
232 self.ownedNFTs[id] != nil: "Asset Token ID does not exist"
233 }
234
235 let refNFT = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
236 let refAssetNFT = refNFT as! &NFT
237
238
239 return refAssetNFT.ownerInfo
240 }
241
242 access(all) view fun getkID(id: UInt64): String {
243 pre {
244 self.ownedNFTs[id] != nil: "Asset Token ID does not exist"
245 }
246
247 let refNFT = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
248 let refAssetNFT = refNFT as! &NFT
249
250
251 return refAssetNFT.kID
252 }
253
254 access(contract) fun depositAsset(token: @{NonFungibleToken.NFT}) {
255 let assetToken <- token as! @NFT
256
257 let oldToken <- self.ownedNFTs[assetToken.id] <- assetToken
258
259 destroy oldToken
260 }
261
262 access(contract) fun transferOwner(id: UInt64, ownerFrom: String, ownerTo: String, songID: String, price: UFix64?, priceUnit: String?, paymentRefInfo: String?, webhookID: String?) {
263 pre {
264 self.ownedNFTs[id] != nil: "Asset Token ID does not exist"
265 }
266
267 let refNFT = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
268 let refAssetNFT = refNFT as! &NFT
269
270 refAssetNFT.transferOwner(id: id, ownerFrom: ownerFrom, ownerTo: ownerTo, songID: songID, price: price, priceUnit: priceUnit, paymentRefInfo: paymentRefInfo, webhookID: webhookID)
271
272 }
273
274 access(contract) fun updateMetadata(id: UInt64, title: String?, description: String?, thumbnail: String?, assetType: String?, ownerInfo: String, metadata: {String:String}?, webhookID: String?) {
275 pre {
276 self.ownedNFTs[id] != nil: "Asset Token ID does not exist"
277 }
278
279 let refNFT = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
280 let refAssetNFT = refNFT as! &NFT
281
282 refAssetNFT.updateMetadata(id: id, title: title, description: description, thumbnail: thumbnail, assetType: assetType, ownerInfo: ownerInfo, metadata: metadata, webhookID:webhookID)
283 emit AssetUpdated(id: id, title: title, description: description, thumbnail: thumbnail, assetType: assetType, ownerInfo: ownerInfo, metadata: metadata, webhookID: webhookID)
284
285 }
286
287 access(contract) fun batchupdateMetadata(ids: [UInt64], title: String?, description: String?, thumbnail: String?, assetType: String?, ownerInfo: String, metadata: {String:String}?, webhookID: String?) {
288 pre {
289 assetType == "private" || assetType == "public" || assetType == nil:
290 "Asset Type must be private or public or null"
291
292 ids.length > 0: "Total length of ids cannot be less than 1"
293 }
294
295 for id in ids {
296 if self.ownedNFTs[id] != nil {
297
298 let refNFT = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
299 let refAssetNFT = refNFT as! &NFT
300
301 refAssetNFT.updateMetadata(id: id, title: title, description: description, thumbnail: thumbnail, assetType: assetType, ownerInfo: ownerInfo, metadata: metadata, webhookID:webhookID)
302 } else {
303 panic("Asset Token ID ".concat(id.toString()).concat(" not owned"))
304 }
305 }
306 emit AssetBatchUpdated(ids: ids, title: title, description: description, thumbnail: thumbnail, assetType: assetType, ownerInfo: ownerInfo, metadata: metadata, webhookID: webhookID)
307 }
308
309
310
311 }
312
313 access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
314 return <- create Collection()
315 }
316
317 access(all) view fun getContractViews(resourceType: Type?): [Type] {
318 return [
319 Type<MetadataViews.NFTCollectionData>(),
320 Type<MetadataViews.NFTCollectionDisplay>()
321 ]
322 }
323
324
325 access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
326 switch viewType {
327 case Type<MetadataViews.NFTCollectionData>():
328 let collectionData = MetadataViews.NFTCollectionData(
329 storagePath: self.CollectionStoragePath,
330 publicPath: self.CollectionPublicPath,
331 publicCollection: Type<&NTest_Trm_Asset_NFT.Collection>(),
332 publicLinkedType: Type<&NTest_Trm_Asset_NFT.Collection>(),
333 createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} {
334 return <-NTest_Trm_Asset_NFT.createEmptyCollection(nftType: Type<@NTest_Trm_Asset_NFT.NFT>())
335 })
336 )
337 return collectionData
338 case Type<MetadataViews.NFTCollectionDisplay>():
339 let media = MetadataViews.Media(
340 file: MetadataViews.HTTPFile(
341 url: "https://www.intertrust.com/wp-content/themes/flat-theme/assets/images/svg/intertrust-header-logoV2.png"
342 ),
343 mediaType: "image/png+xml"
344 )
345 return MetadataViews.NFTCollectionDisplay(
346 name: "The Example Collection",
347 description: "This collection is used as an example to help you develop your next Flow NFT.",
348 externalURL: MetadataViews.ExternalURL("https://www.intertrust.com/marketmaker/"),
349 squareImage: media,
350 bannerImage: media,
351 socials: {
352 "twitter": MetadataViews.ExternalURL("https://x.com/IntertrustTech")
353 }
354 )
355 }
356 return nil
357 }
358
359 access(all) resource NFTMinter {
360
361 /// mintNFT mints a new NFT with a new ID
362 /// and returns it to the calling context
363 access(all) fun mintNFT(
364 collectionRef: &NTest_Trm_Asset_NFT.Collection,
365 title: String,
366 description: String,
367 thumbnail: String,
368 metadata: {String: String},
369 serialNumber: UInt32,
370 url: String,
371 ownerInfo: String,
372 assetType: String,
373 kID: String,
374 songID: String,
375 masterTokenID: UInt64?,
376 webhookID: String?
377 ): UInt64 {
378
379 let tokenID = NTest_Trm_Asset_NFT.totalSupply
380 var finalMasterTokenID = tokenID
381
382 if let tempMasterTokenID = masterTokenID {
383 var masterTokenSerialNumber = collectionRef.getSerialNumber(id: tempMasterTokenID)
384 if masterTokenSerialNumber != 0 { panic("Invalid Master Token ID") }
385 finalMasterTokenID = tempMasterTokenID
386 }
387
388 collectionRef.deposit(token: <- create NFT(id: tokenID,
389 title: title,
390 description: description,
391 thumbnail: thumbnail,
392 metadata: metadata,
393 serialNumber: serialNumber,
394 url: url,
395 ownerInfo: ownerInfo,
396 assetType: assetType,
397 kID: kID,
398 songID: songID,
399 masterTokenID: finalMasterTokenID))
400
401 NTest_Trm_Asset_NFT.totalSupply = tokenID + 1
402
403 return NTest_Trm_Asset_NFT.totalSupply
404 // create a new NFT
405
406 }
407
408
409 }
410
411 access(all) resource Admin {
412
413 access(all) fun transferOwner(collectionRef: &NTest_Trm_Asset_NFT.Collection, id: UInt64, ownerFrom: String, ownerTo: String, songID: String, price: UFix64?, priceUnit: String?, paymentRefInfo: String?, webhookID: String?) {
414
415 collectionRef.transferOwner(id: id, ownerFrom: ownerFrom, ownerTo: ownerTo, songID: songID, price: price, priceUnit: priceUnit, paymentRefInfo: paymentRefInfo, webhookID: webhookID)
416 }
417
418 access(all) fun updateMetadata(collectionRef: &NTest_Trm_Asset_NFT.Collection, id: UInt64, title: String?, description: String?, thumbnail: String?, metadata: {String:String}?, ownerInfo: String, assetType: String?, webhookID: String?) {
419
420 collectionRef.updateMetadata(id: id, title: title, description: description, thumbnail: thumbnail, assetType: assetType, ownerInfo: ownerInfo, metadata: metadata, webhookID: webhookID)
421 }
422 access(all) fun batchupdateMetadata(collectionRef: &NTest_Trm_Asset_NFT.Collection, ids: [UInt64], title: String?, description: String?, thumbnail: String?, metadata: {String:String}?, ownerInfo: String, assetType: String?, webhookID: String?) {
423
424 collectionRef.batchupdateMetadata(ids: ids, title: title, description: description, thumbnail: thumbnail, assetType: assetType, ownerInfo: ownerInfo, metadata: metadata, webhookID: webhookID)
425 }
426
427 access(all) fun depositAsset(collectionRef: &NTest_Trm_Asset_NFT.Collection,title: String, description: String, thumbnail: String, metadata: {String: String}, serialNumber: UInt32, url: String,ownerInfo: String, assetType: String, kID: String,songID: String, masterTokenID: UInt64?,webhookID: String?): UInt64 {
428
429 let tokenID = NTest_Trm_Asset_NFT.totalSupply
430 var finalMasterTokenID = tokenID
431
432 if let tempMasterTokenID = masterTokenID {
433 var masterTokenSerialNumber = collectionRef.getSerialNumber(id: tempMasterTokenID)
434 if masterTokenSerialNumber != 0 { panic("Invalid Master Token ID") }
435 finalMasterTokenID = tempMasterTokenID
436 }
437
438 collectionRef.depositAsset(token: <- create NFT(id: tokenID, title: title, description: description, thumbnail: thumbnail, metadata: metadata, serialNumber: serialNumber, url: url, ownerInfo: ownerInfo, assetType: assetType,kID: kID, songID: songID, masterTokenID: finalMasterTokenID))
439
440 NTest_Trm_Asset_NFT.totalSupply = tokenID + 1
441
442 emit AssetMinted(id: tokenID, title: title, description: description, thumbnail: thumbnail, metadata: metadata, serialNumber: serialNumber, url: url, ownerInfo: ownerInfo, assetType: assetType, kID: kID, songID: songID,masterTokenID: finalMasterTokenID, webhookID: webhookID)
443
444 return NTest_Trm_Asset_NFT.totalSupply
445 // create a new NFT
446
447 }
448 access(all) fun batchdepositAsset(collectionRef: &NTest_Trm_Asset_NFT.Collection, totalCount: UInt32, title: String, description: String, thumbnail: String, metadata: {String: String},startSerialNumber: UInt32, url: String, ownerInfo: String, assetType: String, kID: String, songID: String, masterTokenID: UInt64?, webhookID: String?): UInt64 {
449 pre {
450 totalCount > 0: "Total Count cannot be less than 1"
451 }
452
453 let startTokenID = NTest_Trm_Asset_NFT.totalSupply
454 var tempmasterTokenID = startTokenID
455
456 if masterTokenID != nil {
457 tempmasterTokenID = masterTokenID!
458 }
459
460 var tokenID = startTokenID
461 var counter: UInt32 = 0
462 var serialNumber = startSerialNumber
463
464 while counter < totalCount {
465
466 collectionRef.depositAsset(token: <- create NFT(id: tokenID, title: title, description: description, thumbnail: thumbnail, metadata: metadata, serialNumber: serialNumber, url: url, ownerInfo: ownerInfo, assetType: assetType, kID: kID, songID: songID, masterTokenID: tempmasterTokenID))
467
468 counter = counter + 1
469 tokenID = tokenID + 1
470 serialNumber = serialNumber + 1
471 }
472
473 let endTokenID = tokenID - 1
474 let endSerialNumber = serialNumber - 1
475
476 emit AssetBatchMinted(startID: startTokenID, endID: endTokenID, totalCount: totalCount, startSerialNumber: startSerialNumber, endSerialNumber: endSerialNumber, title: title, description: description, thumbnail: thumbnail, metadata: metadata, url: url, ownerInfo: ownerInfo, assetType: assetType, kID: kID, songID: songID, masterTokenID: tempmasterTokenID, webhookID: webhookID)
477
478 NTest_Trm_Asset_NFT.totalSupply = tokenID
479
480 return NTest_Trm_Asset_NFT.totalSupply
481
482 }
483
484
485 }
486
487 init() {
488 // Set the named paths
489 self.CollectionStoragePath = /storage/NTest_Trm_Asset_NFTCollection
490 self.CollectionPublicPath = /public/NTest_Trm_Asset_NFTCollection
491 self.MinterStoragePath = /storage/NTest_Trm_Asset_NFTMinter
492 self.adminStoragePath = /storage/NTest_Trm_Asset_NFTAdmin
493
494 // First, check to see if a minter resource already exists
495 if self.account.storage.type(at: self.MinterStoragePath) == nil {
496 // Put the minter in storage with access only to admin
497 self.account.storage.save(<-create NFTMinter(), to: self.MinterStoragePath)
498 }
499
500 // First, check to see if a minter resource already exists
501 if self.account.storage.type(at: self.adminStoragePath) == nil {
502 // Put the minter in storage with access only to admin
503 self.account.storage.save(<-create Admin(), to: self.adminStoragePath)
504 }
505
506 self.totalSupply = 0
507
508 }
509}
510