Smart Contract

Utils

A.028d640de9b233fb.Utils

Valid From

83,403,910

Deployed

2h ago
Feb 28, 2026, 10:43:04 PM UTC

Dependents

0 imports
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}