Smart Contract
Utils
A.028d640de9b233fb.Utils
1import NonFungibleToken from 0x1d7e57aa55817448
2import ViewResolver from 0x1d7e57aa55817448
3import MetadataViews from 0x1d7e57aa55817448
4import StringUtils from 0xa340dc0a4ec828ab
5import AddressUtils from 0xa340dc0a4ec828ab
6import NFTCatalog from 0x49a7cda3a1eecc29
7
8access(all) contract Utils {
9 access(all) fun borrowViewResolver(_ t: Type): &{ViewResolver}? {
10 let segments = StringUtils.split(t.identifier, ".")
11 let addr = AddressUtils.parseAddress(segments[1]) ?? panic("borrowViewResolver: unable to parse address")
12 let contractName = segments[2]
13
14 return getAccount(addr).contracts.borrow<&{ViewResolver}>(name: contractName)
15 }
16
17 access(all) fun firstCatalogEntry(_ t: Type): NFTCatalog.NFTCatalogMetadata? {
18 if let catalogEntries = NFTCatalog.getCollectionsForType(nftTypeIdentifier: t.identifier) {
19 for k in catalogEntries.keys {
20 if catalogEntries[k] == true {
21 return NFTCatalog.getCatalogEntry(collectionIdentifier: k)!
22 }
23 }
24 }
25
26 return nil
27 }
28
29 access(all) fun resolveCollectionMetadata(_ t: Type): CollectionMetadata? {
30 // if this type is in the nft catalog, we can just use its data.
31 if let catalogEntry = self.firstCatalogEntry(t) {
32 return CollectionMetadata(catalogEntry, nil, nil)
33 }
34
35 if let vr = self.borrowViewResolver(t) {
36 let display = vr.resolveContractView(resourceType: t, viewType: Type<MetadataViews.NFTCollectionDisplay>()) as! MetadataViews.NFTCollectionDisplay?
37 let data = vr.resolveContractView(resourceType: t, viewType: Type<MetadataViews.NFTCollectionData>()) as! MetadataViews.NFTCollectionData?
38
39 return CollectionMetadata(nil, display, data)
40 }
41
42 return nil
43 }
44
45 access(all) fun resolveContractNftTypes(addr: Address, name: String): [String] {
46 let types: [String] = []
47
48 let acct = getAccount(addr)
49 let c = acct.contracts.get(name: name) ?? panic("contract not found")
50 let pts = c.publicTypes()
51
52 let nftType = Type<@{NonFungibleToken.NFT}>()
53 for t in pts {
54 if t.isSubtype(of: nftType) {
55 types.append(t.identifier)
56 }
57 }
58
59 return types
60 }
61
62 access(all) fun resolveNftMetadata(acct: auth(Storage) &Account, storagePath: StoragePath, id: UInt64): NftMetadata? {
63 let c = acct.storage.borrow<&{NonFungibleToken.CollectionPublic}>(from: storagePath)
64 ?? panic("no collection found at storage path")
65
66 let nft = c.borrowNFT(id)
67 if nft == nil {
68 return nil
69 }
70
71 return NftMetadata(nft!)
72 }
73
74 access(all) struct NftMetadata {
75 access(all) let id: UInt64
76 access(all) let uuid: UInt64
77 access(all) let type: String
78 access(all) let owner: Address?
79 access(all) var serial: UInt64
80 access(all) var displayName: String
81 access(all) var displayThumbnail: String?
82 access(all) var externalUrl: String?
83
84 access(all) var traits: [MetadataViews.Trait]
85 access(all) var editions: [MetadataViews.Edition]
86
87 init(_ nft: &{NonFungibleToken.NFT}) {
88 self.id = nft.id
89 self.uuid = nft.uuid
90 self.type = nft.getType().identifier
91 self.owner = nft.owner?.address
92
93 self.serial = self.id
94 let segments = StringUtils.split(self.type, ".")
95
96 self.displayName = segments[2].concat(" #").concat(self.serial.toString())
97 self.displayThumbnail = nil
98
99 self.externalUrl = nil
100 self.editions = []
101 self.traits = []
102
103 if let s = nft.resolveView(Type<MetadataViews.Serial>()) as! MetadataViews.Serial? {
104 self.serial = s.number
105 }
106
107 if let e = nft.resolveView(Type<MetadataViews.ExternalURL>()) as! MetadataViews.ExternalURL? {
108 self.externalUrl = e.url
109 }
110
111 if let display = nft.resolveView(Type<MetadataViews.Display>()) as! MetadataViews.Display? {
112 self.displayName = display.name
113 self.displayThumbnail = display.thumbnail.uri()
114 }
115
116 if let traits = nft.resolveView(Type<MetadataViews.Traits>()) as! MetadataViews.Traits? {
117 self.traits = traits.traits
118 }
119
120 if let editions = nft.resolveView(Type<MetadataViews.Editions>()) as! MetadataViews.Editions? {
121 self.editions = editions.infoList
122 }
123 }
124 }
125
126 access(all) struct CollectionMetadata {
127 access(all) var inCatalog: Bool
128 access(all) var display: CollectionDisplay?
129 access(all) var data: CollectionData?
130
131 init(_ catalogMetadata: NFTCatalog.NFTCatalogMetadata?, _ collectionDisplay: MetadataViews.NFTCollectionDisplay?, _ collectionData: MetadataViews.NFTCollectionData?) {
132 self.display = nil
133 self.data = nil
134 self.inCatalog = false
135
136 if let c = catalogMetadata {
137 self.display = CollectionDisplay(c.collectionDisplay)
138 self.data = CollectionData(c.collectionData, nil)
139 self.inCatalog = true
140 return
141 }
142
143 if let c = collectionDisplay {
144 self.display = CollectionDisplay(c)
145 }
146
147 if let d = collectionData {
148 self.data = CollectionData(nil, d)
149 }
150 }
151 }
152
153 access(all) struct CollectionDisplay {
154 access(all) let name: String
155 access(all) let description: String
156 access(all) let externalURL: String
157 access(all) let squareImage: Media
158 access(all) let bannerImage: Media
159 access(all) let socials: {String: String}
160
161 init(_ c: MetadataViews.NFTCollectionDisplay) {
162 self.name = c.name
163 self.description = c.description
164 self.externalURL = c.externalURL.url
165 self.squareImage = Media(c.squareImage)
166 self.bannerImage = Media(c.bannerImage)
167
168
169 self.socials = {}
170 for k in c.socials.keys {
171 self.socials[k] = c.socials[k]!.url
172 }
173 }
174 }
175
176 access(all) struct Media {
177 access(all) let uri: String
178 access(all) let fileType: String
179 access(all) let mediaType: String
180
181 init(_ m: MetadataViews.Media) {
182 self.uri = m.file.uri()
183 self.fileType = m.file.getType().identifier
184 self.mediaType = m.mediaType
185 }
186 }
187
188 access(all) struct CollectionData {
189 access(all) var storagePath: StoragePath
190 access(all) var publicPath: PublicPath
191
192 init(_ catalogData: NFTCatalog.NFTCollectionData?, _ collectionData: MetadataViews.NFTCollectionData?) {
193 self.storagePath = /storage/empty
194 self.publicPath = /public/empty
195
196 if let c = catalogData {
197 self.storagePath = c.storagePath
198 self.publicPath = c.publicPath
199 return
200 } else if let c = collectionData {
201 self.storagePath = c.storagePath
202 self.publicPath = c.publicPath
203 return
204 } else {
205 panic("either catalogData or collection data must be non-nil")
206 }
207 }
208 }
209}