Smart Contract

FindViews

A.097bafa4e0b48eef.FindViews

Deployed

2d ago
Feb 26, 2026, 03:12:51 AM UTC

Dependents

3 imports
1import NonFungibleToken from 0x1d7e57aa55817448
2import FungibleToken from 0xf233dcee88fe0abe
3import MetadataViews from 0x1d7e57aa55817448
4import ViewResolver from 0x1d7e57aa55817448
5
6access(all) contract FindViews {
7
8    access(all) struct OnChainFile : MetadataViews.File{
9        access(all) let content: String
10        access(all) let mediaType: String
11        access(all) let protocol: String
12
13        init(content:String, mediaType: String) {
14            self.content=content
15            self.protocol="onChain"
16            self.mediaType=mediaType
17        }
18
19        access(all) view fun uri(): String {
20            return "data:".concat(self.mediaType).concat(",").concat(self.content)
21        }
22    }
23
24    access(all) struct SharedMedia : MetadataViews.File {
25        access(all) let mediaType: String
26        access(all) let pointer: ViewReadPointer
27        access(all) let protocol: String
28
29        init(pointer: ViewReadPointer, mediaType: String) {
30            self.pointer=pointer
31            self.mediaType=mediaType
32            self.protocol="shared"
33
34            if pointer.resolveView(Type<OnChainFile>()) == nil {
35                panic("Cannot create shared media if the pointer does not contain StringMedia")
36            }
37        }
38
39        // todo: this is not working so we have a workaround in the contract
40        access(all) view fun uri(): String {
41            return "data:".concat(self.mediaType).concat(",").concat(self.protocol)
42        }
43    }
44
45    access(all) resource interface VaultViews {
46        access(all) var balance: UFix64
47        access(all) view fun getViews() : [Type]
48        access(all) fun resolveView(_ view: Type): AnyStruct?
49    }
50
51    access(all) struct FTVaultData {
52        access(all) let tokenAlias: String
53        access(all) let storagePath: StoragePath
54        access(all) let receiverPath: PublicPath
55        access(all) let balancePath: PublicPath
56        access(all) let providerPath: PrivatePath
57        access(all) let vaultType: Type
58        access(all) let receiverType: Type
59        access(all) let balanceType: Type
60        access(all) let providerType: Type
61        access(all) let createEmptyVault: (fun(): @{FungibleToken.Vault})
62
63        init(
64            tokenAlias: String,
65            storagePath: StoragePath,
66            receiverPath: PublicPath,
67            balancePath: PublicPath,
68            providerPath: PrivatePath,
69            vaultType: Type,
70            receiverType: Type,
71            balanceType: Type,
72            providerType: Type,
73            createEmptyVault: (fun(): @{FungibleToken.Vault})
74        ) {
75            pre {
76                receiverType.isSubtype(of: Type<&{FungibleToken.Receiver}>()): "Receiver type must include FungibleToken.Receiver interfaces."
77                balanceType.isSubtype(of: Type<&{FungibleToken.Vault}>()): "Balance type must include FungibleToken.Vault interfaces."
78                providerType.isSubtype(of: Type<&{FungibleToken.Provider}>()): "Provider type must include FungibleToken.Provider interface."
79            }
80            self.tokenAlias=tokenAlias
81            self.storagePath=storagePath
82            self.receiverPath=receiverPath
83            self.balancePath=balancePath
84            self.providerPath = providerPath
85            self.vaultType=vaultType
86            self.receiverType=receiverType
87            self.balanceType=balanceType
88            self.providerType = providerType
89            self.createEmptyVault=createEmptyVault
90        }
91    }
92
93    // This is an example taken from Versus
94    access(all) struct CreativeWork {
95        access(all) let artist: String
96        access(all) let name: String
97        access(all) let description: String
98        access(all) let type: String
99
100        init(artist: String, name: String, description: String, type: String) {
101            self.artist=artist
102            self.name=name
103            self.description=description
104            self.type=type
105        }
106    }
107
108    /// A basic pointer that can resolve data and get owner/id/uuid and gype
109    access(all) struct interface Pointer {
110        access(all) let id: UInt64
111        access(all) fun resolveView(_ type: Type) : AnyStruct?
112        access(all) fun getUUID() :UInt64
113        access(all) fun getViews() : [Type]
114        access(all) fun owner() : Address
115        access(all) fun valid() : Bool
116        access(all) fun getItemType() : Type
117        access(all) fun getViewResolver() : &{ViewResolver.Resolver}
118
119        //There are just convenience functions for shared views in the standard
120        access(all) fun getRoyalty() : MetadataViews.Royalties
121        access(all) fun getTotalRoyaltiesCut() : UFix64
122
123        //Requred views
124        access(all) fun getDisplay() : MetadataViews.Display
125        access(all) fun getNFTCollectionData() : MetadataViews.NFTCollectionData
126
127        access(all) fun checkSoulBound() : Bool
128
129    }
130
131    //An interface to say that this pointer can withdraw
132    access(all) struct interface AuthPointer {
133        access(all) fun withdraw() : @AnyResource
134    }
135
136    access(all) struct ViewReadPointer : Pointer {
137        access(self) let cap: Capability<&{ViewResolver.ResolverCollection}>
138        access(all) let id: UInt64
139        access(all) let uuid: UInt64
140        access(all) let itemType: Type
141
142        init(cap: Capability<&{ViewResolver.ResolverCollection}>, id: UInt64) {
143            self.cap=cap
144            self.id=id
145
146            if !self.cap.check() {
147                panic("The capability is not valid.")
148            }
149            let viewResolver=self.cap.borrow()!.borrowViewResolver(id: self.id)!
150            let display = MetadataViews.getDisplay(viewResolver) ?? panic("MetadataViews Display View is not implemented on this NFT.")
151            let nftCollectionData = MetadataViews.getNFTCollectionData(viewResolver) ?? panic("MetadataViews NFTCollectionData View is not implemented on this NFT.")
152            self.uuid=viewResolver.uuid
153            self.itemType=viewResolver.getType()
154        }
155
156        access(all) fun resolveView(_ type: Type) : AnyStruct? {
157            return self.getViewResolver().resolveView(type)
158        }
159
160        access(all) fun getUUID() :UInt64{
161            return self.uuid
162        }
163
164        access(all) fun getViews() : [Type]{
165            return self.getViewResolver().getViews()
166        }
167
168        access(all) fun owner() : Address {
169            return self.cap.address
170        }
171
172        access(all) fun getTotalRoyaltiesCut() :UFix64 {
173            var total=0.0
174            for royalty in self.getRoyalty().getRoyalties() {
175                total = total + royalty.cut
176            }
177            return total
178        }
179
180        access(all) fun getRoyalty() : MetadataViews.Royalties {
181            if let v = MetadataViews.getRoyalties(self.getViewResolver()) {
182                return v
183            }
184            return MetadataViews.Royalties([])
185        }
186
187        access(all) fun valid() : Bool {
188            if !self.cap.check() || self.cap.borrow()!.borrowViewResolver(id: self.id) == nil {
189                return false
190            }
191            return true
192        }
193
194        access(all) fun getItemType() : Type {
195            return self.itemType
196        }
197
198        access(all) fun getViewResolver() : &{ViewResolver.Resolver} {
199            let nft=self.cap.borrow()!.borrowViewResolver(id: self.id) ?? panic("The capability of view pointer is not linked.")
200            return nft
201
202        }
203
204        access(all) fun getDisplay() : MetadataViews.Display {
205            if let v = MetadataViews.getDisplay(self.getViewResolver()) {
206                return v
207            }
208            panic("MetadataViews Display View is not implemented on this NFT.")
209        }
210
211        access(all) fun getNFTCollectionData() : MetadataViews.NFTCollectionData {
212            if let v = MetadataViews.getNFTCollectionData(self.getViewResolver()) {
213                return v
214            }
215            panic("MetadataViews NFTCollectionData View is not implemented on this NFT.")
216        }
217
218        access(all) fun checkSoulBound() : Bool {
219            return FindViews.checkSoulBound(self.getViewResolver())
220        }
221    }
222
223
224    access(all) fun getNounce(_ viewResolver: &{ViewResolver.Resolver}) : UInt64 {
225        if let nounce = viewResolver.resolveView(Type<FindViews.Nounce>()) {
226            if let v = nounce as? FindViews.Nounce {
227                return v.nounce
228            }
229        }
230        return 0
231    }
232
233    access(all) struct AuthNFTPointer : Pointer, AuthPointer{
234        access(self) let cap: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.CollectionPublic, NonFungibleToken.Provider, ViewResolver.ResolverCollection}>
235        access(all) let id: UInt64
236        access(all) let nounce: UInt64
237        access(all) let uuid: UInt64
238        access(all) let itemType: Type
239
240        init(cap: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection, NonFungibleToken.Provider, ViewResolver.ResolverCollection}>, id: UInt64) {
241            self.cap=cap
242            self.id=id
243
244            if !self.cap.check() {
245                panic("The capability is not valid.")
246            }
247
248            let collection = self.cap.borrow() ?? panic("could not find collection")
249            let viewResolver=collection.borrowNFT(self.id) ?? panic("could not borrow nft")
250            let display = MetadataViews.getDisplay(viewResolver) ?? panic("MetadataViews Display View is not implemented on this NFT.")
251            let nftCollectionData = MetadataViews.getNFTCollectionData(viewResolver) ?? panic("MetadataViews NFTCollectionData View is not implemented on this NFT.")
252            self.nounce=FindViews.getNounce(viewResolver)
253            self.uuid=viewResolver.uuid
254            self.itemType=viewResolver.getType()
255        }
256
257        access(all) fun getViewResolver() : &{ViewResolver.Resolver} {
258            let cap = self.cap.borrow()!
259            let viewResolver = cap.borrowNFT(self.id) ?? panic("The capability of view pointer is not linked.")
260            return viewResolver 
261        }
262
263        access(all) fun resolveView(_ type: Type) : AnyStruct? {
264            return self.getViewResolver().resolveView(type)
265        }
266
267        access(all) fun getUUID() :UInt64{
268            return self.uuid
269        }
270
271        access(all) fun getViews() : [Type]{
272            return self.getViewResolver().getViews()
273        }
274
275        access(all) fun valid() : Bool {
276            if !self.cap.check() {
277                return false
278            }
279
280            let collection = self.cap.borrow()! 
281
282            let collectionType=collection.getType()
283            if collectionType.isRecovered {
284                return false
285            }
286
287            let nft= collection.borrowNFT(self.id)
288
289            if nft ==nil {
290                return false
291            }
292
293            if let nounce = nft!.resolveView(Type<FindViews.Nounce>()) {
294                if let v = nounce as? FindViews.Nounce {
295                    return v.nounce==self.nounce
296                }
297            }
298            return true
299        }
300
301        access(all) fun getTotalRoyaltiesCut() :UFix64 {
302            var total=0.0
303            for royalty in self.getRoyalty().getRoyalties() {
304                total = total + royalty.cut
305            }
306            return total
307        }
308
309        access(all) fun getRoyalty() : MetadataViews.Royalties {
310            if let v = MetadataViews.getRoyalties(self.getViewResolver()) {
311                return v
312            }
313            return MetadataViews.Royalties([])
314        }
315
316        access(all) fun getDisplay() : MetadataViews.Display {
317            if let v = MetadataViews.getDisplay(self.getViewResolver()) {
318                return v
319            }
320            panic("MetadataViews Display View is not implemented on this NFT.")
321        }
322
323        access(all) fun getNFTCollectionData() : MetadataViews.NFTCollectionData {
324            if let v = MetadataViews.getNFTCollectionData(self.getViewResolver()) {
325                return v
326            }
327            panic("MetadataViews NFTCollectionData View is not implemented on this NFT.")
328        }
329
330        access(all) fun withdraw() :@{NonFungibleToken.NFT} {
331            if !self.cap.check() {
332                panic("The pointer capability is invalid.")
333            }
334            return <- self.cap.borrow()!.withdraw(withdrawID: self.id)
335        }
336
337        access(all) fun deposit(_ nft: @{NonFungibleToken.NFT}){
338            if !self.cap.check(){
339                panic("The pointer capablity is invalid.")
340            }
341            self.cap.borrow()!.deposit(token: <- nft)
342        }
343
344        access(all) fun owner() : Address {
345            return self.cap.address
346        }
347
348        access(all) fun getItemType() : Type {
349            return self.itemType
350        }
351
352        access(all) fun checkSoulBound() : Bool {
353            return FindViews.checkSoulBound(self.getViewResolver())
354        }
355    }
356
357    access(all) fun createViewReadPointer(address:Address, path:PublicPath, id:UInt64) : ViewReadPointer {
358        let cap=	getAccount(address).capabilities.get<&{ViewResolver.ResolverCollection}>(path)
359        let pointer= FindViews.ViewReadPointer(cap: cap, id: id)
360        return pointer
361    }
362
363    access(all) struct Nounce {
364        access(all) let nounce: UInt64
365
366        init(_ nounce: UInt64) {
367            self.nounce=nounce
368        }
369    }
370
371    access(all) struct SoulBound {
372
373        access(all) let message: String
374
375        init(_ message:String) {
376            self.message=message
377
378        }
379    }
380
381    access(all) fun checkSoulBound(_ viewResolver: &{ViewResolver.Resolver}) : Bool {
382        if let soulBound = viewResolver.resolveView(Type<FindViews.SoulBound>()) {
383            if let v = soulBound as? FindViews.SoulBound {
384                return true
385            }
386        }
387        return false
388    }
389
390    access(all) fun getDapperAddress(): Address {
391        switch FindViews.account.address.toString() {
392        case "0x097bafa4e0b48eef":
393            //mainnet
394            return 0xead892083b3e2c6c
395        case  "0x35717efbbce11c74":
396            //testnet
397            return 0x82ec283f88a62e65
398        default:
399            //emulator
400            return 0x01cf0e2f2f715450
401        }
402    }
403}
404