Smart Contract
FTViewUtils
A.15a918087ab12d86.FTViewUtils
1/**
2> Author: Fixes Lab <https://github.com/fixes-world/>
3
4# Token List - A on-chain list of Flow Standard Fungible Tokens (FTs).
5
6This is the Fungible Token view utilties contract of the Token List.
7
8*/
9import MetadataViews from 0x1d7e57aa55817448
10import ViewResolver from 0x1d7e57aa55817448
11import FungibleToken from 0xf233dcee88fe0abe
12import FungibleTokenMetadataViews from 0xf233dcee88fe0abe
13
14access(all) contract FTViewUtils {
15
16 // ----- Entitlement -----
17
18 // An entitlement for allowing edit the FT View Data
19 access(all) entitlement Editable
20
21 /* ---- Events ---- */
22
23 access(all) event FTViewStoragePathUpdated(
24 address: Address,
25 contractName: String,
26 storagePath: StoragePath
27 )
28
29 access(all) event FTVaultDataUpdated(
30 address: Address,
31 contractName: String,
32 storagePath: StoragePath,
33 receiverPath: PublicPath,
34 metadataPath: PublicPath,
35 receiverType: Type,
36 metadataType: Type
37 )
38
39 access(all) event FTDisplayUpdated(
40 address: Address,
41 contractName: String,
42 name: String?,
43 symbol: String?,
44 description: String?,
45 externalURL: String?,
46 logo: String?,
47 socials: {String: String}
48 )
49
50 /// The struct interface for the Fungible Token Identity
51 ///
52 access(all) struct interface TokenIdentity {
53 /// Build type
54 access(all)
55 view fun buildType(): Type
56 /// Get Type identifier
57 access(all)
58 view fun toString(): String {
59 return self.buildType().identifier
60 }
61 }
62
63 /// The struct for the Fungible Token Identity
64 ///
65 access(all) struct FTIdentity: TokenIdentity {
66 access(all)
67 let address: Address
68 access(all)
69 let contractName: String
70
71 view init(
72 _ address: Address,
73 _ contractName: String
74 ) {
75 self.address = address
76 self.contractName = contractName
77 }
78
79 access(all)
80 view fun buildType(): Type {
81 return FTViewUtils.buildFTVaultType(self.address, self.contractName)
82 ?? panic("Could not build the FT Type")
83 }
84
85 /// Borrow the Fungible Token Contract
86 ///
87 access(all)
88 fun borrowFungibleTokenContract(): &{FungibleToken} {
89 return getAccount(self.address)
90 .contracts.borrow<&{FungibleToken}>(name: self.contractName)
91 ?? panic("Could not borrow the FungibleToken contract reference")
92 }
93 }
94
95 /// The struct for the Fungible Token Vault Data with Source
96 ///
97 access(all) struct FTVaultDataWithSource {
98 access(all)
99 let source: Address?
100 access(all)
101 let vaultData: FungibleTokenMetadataViews.FTVaultData
102
103 view init(
104 _ source: Address?,
105 _ vaultData: FungibleTokenMetadataViews.FTVaultData
106 ) {
107 self.source = source
108 self.vaultData = vaultData
109 }
110 }
111
112 /// The struct for the Fungible Token Display with Source
113 ///
114 access(all) struct FTDisplayWithSource {
115 access(all)
116 let source: Address?
117 access(all)
118 let display: FungibleTokenMetadataViews.FTDisplay
119
120 view init(
121 _ source: Address?,
122 _ display: FungibleTokenMetadataViews.FTDisplay
123 ) {
124 self.source = source
125 self.display = display
126 }
127 }
128
129 /// The struct for the Fungible Token Paths
130 ///
131 access(all) struct StandardTokenPaths {
132 access(all)
133 let vaultPath: StoragePath
134 access(all)
135 let balancePath: PublicPath
136 access(all)
137 let receiverPath: PublicPath
138
139 view init(
140 vaultPath: StoragePath,
141 balancePath: PublicPath,
142 receiverPath: PublicPath,
143 ) {
144 self.vaultPath = vaultPath
145 self.balancePath = balancePath
146 self.receiverPath = receiverPath
147 }
148 }
149
150 /// The struct interface for the Bridged Token View
151 access(all) struct interface IBridgedTokenView {
152 access(all)
153 let evmAddress: String
154 }
155
156 /// The interface for the Token View
157 access(all) struct interface ITokenView {
158 access(all)
159 let tags: [String]
160 access(all)
161 let dataSource: Address?
162
163 access(all)
164 view fun getIdentity(): {TokenIdentity}
165 }
166
167 /// The struct for the Fungible Token List View
168 ///
169 access(all) struct StandardTokenView: ITokenView {
170 access(all)
171 let identity: FTIdentity
172 access(all)
173 let decimals: UInt8
174 access(all)
175 let tags: [String]
176 access(all)
177 let dataSource: Address?
178 access(all)
179 let paths: StandardTokenPaths?
180 access(all)
181 let display: FTDisplayWithSource?
182
183 view init(
184 identity: FTIdentity,
185 decimals: UInt8,
186 tags: [String],
187 dataSource: Address?,
188 paths: StandardTokenPaths?,
189 display: FTDisplayWithSource?,
190 ) {
191 self.identity = identity
192 self.decimals = decimals
193 self.tags = tags
194 self.dataSource = dataSource
195 self.paths = paths
196 self.display = display
197 }
198
199 access(all)
200 view fun getIdentity(): {TokenIdentity} {
201 return self.identity
202 }
203 }
204
205 /// The struct for the Bridged Token View
206 ///
207 access(all) struct BridgedTokenView: ITokenView, IBridgedTokenView {
208 access(all)
209 let identity: FTIdentity
210 access(all)
211 let evmAddress: String
212 access(all)
213 let decimals: UInt8
214 access(all)
215 let tags: [String]
216 access(all)
217 let dataSource: Address?
218 access(all)
219 let paths: StandardTokenPaths?
220 access(all)
221 let display: FTDisplayWithSource?
222
223 view init(
224 identity: FTIdentity,
225 evmAddress: String,
226 decimals: UInt8,
227 tags: [String],
228 dataSource: Address?,
229 paths: StandardTokenPaths?,
230 display: FTDisplayWithSource?,
231 ) {
232 self.identity = identity
233 self.evmAddress = evmAddress
234 self.decimals = decimals
235 self.tags = tags
236 self.dataSource = dataSource
237 self.paths = paths
238 self.display = display
239 }
240
241 access(all)
242 view fun getIdentity(): {TokenIdentity} {
243 return self.identity
244 }
245 }
246
247 /// The enum for the Evaluation
248 ///
249 access(all) enum Evaluation: UInt8 {
250 access(all) case UNVERIFIED
251 access(all) case PENDING
252 access(all) case VERIFIED
253 access(all) case FEATURED
254 access(all) case BLOCKED
255 }
256
257 /// The struct for the Review Comment
258 ///
259 access(all) struct ReviewComment {
260 access(all)
261 let comment: String
262 access(all)
263 let by: Address
264 access(all)
265 let at: UInt64
266
267 view init(_ comment: String, _ by: Address) {
268 self.comment = comment
269 self.by = by
270 self.at = UInt64(getCurrentBlock().timestamp)
271 }
272 }
273
274 /// The struct for the FT Review
275 ///
276 access(all) struct FTReview {
277 access(all)
278 let comments: [ReviewComment]
279 access(all)
280 let tags: [String]
281 access(all)
282 var evalRank: Evaluation
283
284 init(
285 _ rank: Evaluation,
286 ) {
287 self.evalRank = rank
288 self.tags = []
289 self.comments = []
290 }
291
292 /// Get tags
293 ///
294 access(all)
295 view fun getTags(): [String] {
296 return self.tags
297 }
298
299 /// Get getEvaluationRank
300 ///
301 access(all)
302 view fun getEvaluationRank(): Evaluation {
303 return self.evalRank
304 }
305
306 /// Update the evaluation rank
307 ///
308 access(all)
309 fun updateEvaluationRank(
310 _ rank: Evaluation
311 ) {
312 self.evalRank = rank
313 }
314
315 /// Add a new comment to the review
316 ///
317 access(all)
318 fun addComment(_ comment: String, _ by: Address) {
319 self.comments.append(ReviewComment(comment, by))
320 }
321
322 /// Add a new tag to the review
323 ///
324 access(all)
325 fun addTag(_ tag: String): Bool {
326 if !self.tags.contains(tag) {
327 self.tags.append(tag)
328 return true
329 }
330 return false
331 }
332 }
333
334 /// The struct for the Reviewer Info
335 ///
336 access(all) struct ReviewerInfo {
337 access(all)
338 let address: Address
339 access(all)
340 let verified: Bool
341 access(all)
342 let name: String?
343 access(all)
344 let url: String?
345 access(all)
346 let managedTokenAmt: Int
347 access(all)
348 let reviewedTokenAmt: Int
349 access(all)
350 let customziedTokenAmt: Int
351
352 view init(
353 address: Address,
354 verified: Bool,
355 name: String?,
356 url: String?,
357 _ managedTokenAmt: Int,
358 _ reviewedTokenAmt: Int,
359 _ customziedTokenAmt: Int,
360 ) {
361 self.address = address
362 self.verified = verified
363 self.name = name
364 self.url = url
365 self.managedTokenAmt = managedTokenAmt
366 self.reviewedTokenAmt = reviewedTokenAmt
367 self.customziedTokenAmt = customziedTokenAmt
368 }
369 }
370
371 /** Editable FTView */
372
373 /// The enum for the FT Capability Path
374 ///
375 access(all) enum FTCapPath: UInt8 {
376 access(all) case receiver
377 access(all) case metadata
378 access(all) case provider
379 }
380
381 /// The interface for the Editable FT View Data
382 ///
383 access(all) resource interface EditableFTViewDataInterface {
384 /// Identity of the FT
385 access(all)
386 let identity: FTIdentity
387 // ----- FT Vault Data -----
388 /// Get the Storage Path
389 access(all)
390 view fun getStoragePath(): StoragePath
391 /// Get the Receiver Path
392 access(all)
393 view fun getReceiverPath(): PublicPath?
394 /// Get the Metadata Path
395 access(all)
396 view fun getMetadataPath(): PublicPath?
397 /// Get the Provider Path
398 access(all)
399 view fun getProviderPath(): PrivatePath?
400 /// Get the Capability Path
401 access(all)
402 view fun getCapabilityType(_ capPath: FTCapPath): Type?
403 // --- default implementation ---
404 /// Check if the FT View Data is initialized
405 ///
406 access(all)
407 view fun isInitialized(): Bool {
408 return self.getReceiverPath() != nil &&
409 self.getMetadataPath() != nil &&
410 self.getProviderPath() != nil &&
411 self.getCapabilityType(FTCapPath.receiver) != nil &&
412 self.getCapabilityType(FTCapPath.metadata) != nil &&
413 self.getCapabilityType(FTCapPath.provider) != nil
414 }
415 /// Get the FT Vault Data
416 ///
417 access(all)
418 fun getFTVaultData(): FungibleTokenMetadataViews.FTVaultData {
419 pre {
420 self.isInitialized(): "FT View Data is not initialized"
421 }
422 let ftRef = self.identity.borrowFungibleTokenContract()
423 let ftType = self.identity.buildType()
424 return FungibleTokenMetadataViews.FTVaultData(
425 storagePath: self.getStoragePath(),
426 receiverPath: self.getReceiverPath()!,
427 metadataPath: self.getMetadataPath()!,
428 receiverLinkedType: Type<&{FungibleToken.Receiver}>(),
429 metadataLinkedType: Type<&{FungibleToken.Vault}>(),
430 createEmptyVaultFunction: (fun (): @{FungibleToken.Vault} {
431 return <- ftRef.createEmptyVault(vaultType: ftType)
432 })
433 )
434 }
435 }
436
437 /// The interface for the Editable FT View Display
438 ///
439 access(all) resource interface EditableFTViewDisplayInterface: ViewResolver.Resolver {
440 /// Identity of the FT
441 access(all)
442 let identity: FTIdentity
443 // ----- FT Display -----
444 access(all)
445 view fun getSymbol(): String?
446 access(all)
447 view fun getName(): String?
448 access(all)
449 view fun getDescription(): String?
450 access(all)
451 view fun getExternalURL(): MetadataViews.ExternalURL?
452 access(all)
453 view fun getSocials(): {String: MetadataViews.ExternalURL}
454 access(all)
455 fun getLogos(): MetadataViews.Medias
456 // --- default implementation ---
457 /// Get the FT Display
458 ///
459 access(all)
460 fun getFTDisplay(): FungibleTokenMetadataViews.FTDisplay {
461 return FungibleTokenMetadataViews.FTDisplay(
462 name: self.getName() ?? "Unknown Token",
463 symbol: self.getSymbol() ?? "NONE",
464 description: self.getDescription() ?? "No Description",
465 externalURL: self.getExternalURL() ?? MetadataViews.ExternalURL("https://fixes.world"),
466 logos: self.getLogos(),
467 socials: self.getSocials()
468 )
469 }
470 }
471
472 /// The interface for the FT View Data Editor
473 ///
474 access(all) resource interface FTViewDataEditor: EditableFTViewDataInterface {
475 /// Update the Storage Path
476 access(Editable)
477 fun updateStoragePath(_ storagePath: StoragePath)
478 /// Set the FT Vault Data
479 access(Editable)
480 fun initializeVaultData(
481 receiverPath: PublicPath,
482 metadataPath: PublicPath,
483 receiverType: Type,
484 metadataType: Type,
485 )
486 }
487
488 /// The interface for the FT View Display Editor
489 ///
490 access(all) resource interface FTViewDisplayEditor: EditableFTViewDisplayInterface {
491 /// Set the FT Display
492 access(Editable)
493 fun setFTDisplay(
494 name: String?,
495 symbol: String?,
496 description: String?,
497 externalURL: String?,
498 logo: String?,
499 socials: {String: String}
500 )
501 }
502
503 /// The Resource for the FT Display
504 ///
505 access(all) resource EditableFTDisplay: FTViewDisplayEditor, EditableFTViewDisplayInterface, ViewResolver.Resolver {
506 access(all)
507 let identity: FTIdentity
508 access(contract)
509 let metadata: {String: String}
510
511 init(
512 _ address: Address,
513 _ contractName: String,
514 ) {
515 self.identity = FTIdentity(address, contractName)
516 self.metadata = {}
517 }
518
519 /// Set the FT Display
520 ///
521 access(Editable)
522 fun setFTDisplay(
523 name: String?,
524 symbol: String?,
525 description: String?,
526 externalURL: String?,
527 logo: String?,
528 socials: {String: String}
529 ) {
530 // set name
531 if name != nil {
532 self.metadata["name"] = name!
533 }
534 // set symbol
535 if symbol != nil {
536 self.metadata["symbol"] = symbol!
537 }
538 // set description
539 if description != nil {
540 self.metadata["description"] = description!
541 }
542 // set external URL
543 if externalURL != nil {
544 self.metadata["externalURL"] = externalURL!
545 }
546 // set logo
547 if logo != nil {
548 // the last 3 chars are file type, check the type
549 let fileType = logo!.slice(from: logo!.length - 3, upTo: logo!.length)
550 if fileType == "png" {
551 self.metadata["logo:png"] = logo!
552 } else if fileType == "svg" {
553 self.metadata["logo:svg"] = logo!
554 } else if fileType == "jpg" {
555 self.metadata["logo:jpg"] = logo!
556 } else {
557 self.metadata["logo"] = logo!
558 }
559 }
560 // set socials
561 for key in socials.keys {
562 self.metadata["social:".concat(key)] = socials[key]!
563 }
564
565 // Emit the event
566 emit FTDisplayUpdated(
567 address: self.identity.address,
568 contractName: self.identity.contractName,
569 name: name,
570 symbol: symbol,
571 description: description,
572 externalURL: externalURL,
573 logo: logo,
574 socials: socials
575 )
576 }
577
578 /** ---- Implement the EditableFTViewDisplayInterface ---- */
579
580 access(all)
581 view fun getSymbol(): String? {
582 return self.metadata["symbol"]
583 }
584
585 access(all)
586 view fun getName(): String? {
587 return self.metadata["name"]
588 }
589
590 access(all)
591 view fun getDescription(): String? {
592 return self.metadata["description"]
593 }
594
595 access(all)
596 view fun getExternalURL(): MetadataViews.ExternalURL? {
597 let url = self.metadata["externalURL"]
598 return url != nil ? MetadataViews.ExternalURL(url!) : nil
599 }
600
601 access(all)
602 fun getLogos(): MetadataViews.Medias {
603 let medias: [MetadataViews.Media] = []
604 if self.metadata["logo:png"] != nil {
605 medias.append(MetadataViews.Media(
606 file: MetadataViews.HTTPFile(url: self.metadata["logo:png"]!),
607 mediaType: "image/png" // default is png
608 ))
609 }
610 if self.metadata["logo:svg"] != nil {
611 medias.append(MetadataViews.Media(
612 file: MetadataViews.HTTPFile(url: self.metadata["logo:svg"]!),
613 mediaType: "image/svg+xml"
614 ))
615 }
616 if self.metadata["logo:jpg"] != nil {
617 medias.append(MetadataViews.Media(
618 file: MetadataViews.HTTPFile(url: self.metadata["logo:jpg"]!),
619 mediaType: "image/jpeg"
620 ))
621 }
622 if self.metadata["logo"] != nil {
623 medias.append(MetadataViews.Media(
624 file: MetadataViews.HTTPFile(url: self.metadata["logo"]!),
625 mediaType: "image/*"
626 ))
627 }
628 // add default icon
629 if medias.length == 0 {
630 let ticker = self.getSymbol() ?? self.getName() ?? "NONE"
631 let tickNameSize = 80 + (10 - ticker.length > 0 ? 10 - ticker.length : 0) * 12
632 let svgStr = "data:image/svg+xml;utf8,"
633 .concat("%3Csvg%20xmlns%3D%5C%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%5C%22%20viewBox%3D%5C%22-256%20-256%20512%20512%5C%22%20width%3D%5C%22512%5C%22%20height%3D%5C%22512%5C%22%3E")
634 .concat("%3Cdefs%3E%3ClinearGradient%20gradientUnits%3D%5C%22userSpaceOnUse%5C%22%20x1%3D%5C%220%5C%22%20y1%3D%5C%22-240%5C%22%20x2%3D%5C%220%5C%22%20y2%3D%5C%22240%5C%22%20id%3D%5C%22gradient-0%5C%22%20gradientTransform%3D%5C%22matrix(0.908427%2C%20-0.41805%2C%200.320369%2C%200.696163%2C%20-69.267567%2C%20-90.441103)%5C%22%3E%3Cstop%20offset%3D%5C%220%5C%22%20style%3D%5C%22stop-color%3A%20rgb(244%2C%20246%2C%20246)%3B%5C%22%3E%3C%2Fstop%3E%3Cstop%20offset%3D%5C%221%5C%22%20style%3D%5C%22stop-color%3A%20rgb(35%2C%20133%2C%2091)%3B%5C%22%3E%3C%2Fstop%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E")
635 .concat("%3Cellipse%20style%3D%5C%22fill%3A%20rgb(149%2C%20225%2C%20192)%3B%20stroke-width%3A%201rem%3B%20paint-order%3A%20fill%3B%20stroke%3A%20url(%23gradient-0)%3B%5C%22%20ry%3D%5C%22240%5C%22%20rx%3D%5C%22240%5C%22%3E%3C%2Fellipse%3E")
636 .concat("%3Ctext%20style%3D%5C%22dominant-baseline%3A%20middle%3B%20fill%3A%20rgb(80%2C%20213%2C%20155)%3B%20font-family%3A%20system-ui%2C%20sans-serif%3B%20text-anchor%3A%20middle%3B%5C%22%20fill-opacity%3D%5C%220.2%5C%22%20y%3D%5C%22-12%5C%22%20font-size%3D%5C%22420%5C%22%3E%F0%9D%94%89%3C%2Ftext%3E")
637 .concat("%3Ctext%20style%3D%5C%22dominant-baseline%3A%20middle%3B%20fill%3A%20rgb(244%2C%20246%2C%20246)%3B%20font-family%3A%20system-ui%2C%20sans-serif%3B%20text-anchor%3A%20middle%3B%20font-style%3A%20italic%3B%20font-weight%3A%20700%3B%5C%22%20y%3D%5C%2212%5C%22%20font-size%3D%5C%22").concat(tickNameSize.toString()).concat("%5C%22%3E")
638 .concat(ticker).concat("%3C%2Ftext%3E%3C%2Fsvg%3E")
639 medias.append(MetadataViews.Media(
640 file: MetadataViews.HTTPFile(url: svgStr),
641 mediaType: "image/svg+xml"
642 ))
643 }
644 return MetadataViews.Medias(medias)
645 }
646
647 access(all)
648 view fun getSocials(): {String: MetadataViews.ExternalURL} {
649 let ret: {String: MetadataViews.ExternalURL} = {}
650 let socialKey = "social:"
651 let socialKeyLen = socialKey.length
652 for key in self.metadata.keys {
653 if key.length >= socialKeyLen && key.slice(from: 0, upTo: socialKey.length) == socialKey {
654 let socialName = key.slice(from: socialKey.length, upTo: key.length)
655 ret[socialName] = MetadataViews.ExternalURL(self.metadata[key]!)
656 }
657 }
658 return ret
659 }
660
661 /* --- Implement the MetadataViews.Resolver --- */
662
663 access(all)
664 view fun getViews(): [Type] {
665 return [
666 Type<FungibleTokenMetadataViews.FTDisplay>()
667 ]
668 }
669
670 access(all)
671 fun resolveView(_ view: Type): AnyStruct? {
672 switch view {
673 case Type<FungibleTokenMetadataViews.FTDisplay>():
674 return self.getFTDisplay()
675 }
676 return nil
677 }
678 }
679
680 /// Create the FT View Data
681 ///
682 access(all)
683 fun createEditableFTDisplay(
684 _ address: Address,
685 _ contractName: String,
686 ): @EditableFTDisplay {
687 return <- create EditableFTDisplay(address, contractName)
688 }
689
690 /// The Resource for the FT View
691 ///
692 access(all) resource EditableFTView: FTViewDataEditor, EditableFTViewDataInterface, FTViewDisplayEditor, EditableFTViewDisplayInterface, ViewResolver.Resolver {
693 access(self)
694 let display: @EditableFTDisplay
695 access(all)
696 let identity: FTIdentity
697 access(contract)
698 var storagePath: StoragePath
699 access(contract)
700 let capabilityPaths: {FTCapPath: CapabilityPath}
701 access(contract)
702 let capabilityTypes: {FTCapPath: Type}
703
704 init(
705 _ address: Address,
706 _ contractName: String,
707 _ storagePath: StoragePath,
708 ) {
709 self.identity = FTIdentity(address, contractName)
710 self.display <- create EditableFTDisplay(address, contractName)
711 self.capabilityPaths = {}
712 self.capabilityTypes = {}
713 self.storagePath = storagePath
714 }
715
716 // ---- Writable Functions ----
717
718 /// Update the Storage Path
719 ///
720 access(Editable)
721 fun updateStoragePath(_ storagePath: StoragePath) {
722 self.storagePath = storagePath
723
724 emit FTViewStoragePathUpdated(
725 address: self.identity.address,
726 contractName: self.identity.contractName,
727 storagePath: storagePath
728 )
729 }
730
731 /// Initialize the FT View Data
732 ///
733 access(Editable)
734 fun initializeVaultData(
735 receiverPath: PublicPath,
736 metadataPath: PublicPath,
737 receiverType: Type,
738 metadataType: Type,
739 ) {
740 self.capabilityPaths[FTCapPath.receiver] = receiverPath
741 self.capabilityPaths[FTCapPath.metadata] = metadataPath
742 self.capabilityTypes[FTCapPath.receiver] = receiverType
743 self.capabilityTypes[FTCapPath.metadata] = metadataType
744
745 // Emit the event
746 emit FTVaultDataUpdated(
747 address: self.identity.address,
748 contractName: self.identity.contractName,
749 storagePath: self.storagePath,
750 receiverPath: receiverPath,
751 metadataPath: metadataPath,
752 receiverType: receiverType,
753 metadataType: metadataType
754 )
755 }
756
757 /** ---- Implement the EditableFTViewDataInterface ---- */
758
759 access(all)
760 view fun getStoragePath(): StoragePath {
761 return self.storagePath
762 }
763
764 /// Get the Receiver Path
765 access(all)
766 view fun getReceiverPath(): PublicPath? {
767 return self.capabilityPaths[FTCapPath.receiver] as! PublicPath?
768 }
769
770 /// Get the Metadata Path
771 access(all)
772 view fun getMetadataPath(): PublicPath? {
773 return self.capabilityPaths[FTCapPath.metadata] as! PublicPath?
774 }
775
776 /// Get the Provider Path
777 access(all)
778 view fun getProviderPath(): PrivatePath? {
779 return self.capabilityPaths[FTCapPath.provider] as! PrivatePath?
780 }
781
782 /// Get the Capability Path
783 access(all)
784 view fun getCapabilityType(_ capPath: FTCapPath): Type? {
785 return self.capabilityTypes[capPath]
786 }
787
788 /** ---- Implement the FTViewDataEditor ---- */
789
790 /// Set the FT Display
791 ///
792 access(Editable)
793 fun setFTDisplay(
794 name: String?,
795 symbol: String?,
796 description: String?,
797 externalURL: String?,
798 logo: String?,
799 socials: {String: String}
800 ) {
801 self.display.setFTDisplay(
802 name: name,
803 symbol: symbol,
804 description: description,
805 externalURL: externalURL,
806 logo: logo,
807 socials: socials
808 )
809 }
810
811 /** ---- Implement the FTViewDisplayInterface ---- */
812
813 access(all)
814 view fun getSymbol(): String? {
815 return self.display.getSymbol()
816 }
817
818 access(all)
819 view fun getName(): String? {
820 return self.display.getName()
821 }
822
823 access(all)
824 view fun getDescription(): String? {
825 return self.display.getDescription()
826 }
827
828 access(all)
829 view fun getExternalURL(): MetadataViews.ExternalURL? {
830 return self.display.getExternalURL()
831 }
832
833 access(all)
834 fun getLogos(): MetadataViews.Medias {
835 return self.display.getLogos()
836 }
837
838 access(all)
839 view fun getSocials(): {String: MetadataViews.ExternalURL} {
840 return self.display.getSocials()
841 }
842
843 /* --- Implement the MetadataViews.Resolver --- */
844
845 access(all)
846 view fun getViews(): [Type] {
847 return [
848 Type<MetadataViews.ExternalURL>(),
849 Type<FungibleTokenMetadataViews.FTView>(),
850 Type<FungibleTokenMetadataViews.FTDisplay>(),
851 Type<FungibleTokenMetadataViews.FTVaultData>()
852 ]
853 }
854
855 access(all)
856 fun resolveView(_ view: Type): AnyStruct? {
857 switch view {
858 case Type<MetadataViews.ExternalURL>():
859 return self.getExternalURL()
860 case Type<FungibleTokenMetadataViews.FTView>():
861 return FungibleTokenMetadataViews.FTView(
862 ftDisplay: self.getFTDisplay(),
863 ftVaultData: self.getFTVaultData()
864 )
865 case Type<FungibleTokenMetadataViews.FTDisplay>():
866 return self.getFTDisplay()
867 case Type<FungibleTokenMetadataViews.FTVaultData>():
868 return self.getFTVaultData()
869 }
870 return nil
871 }
872 }
873
874 /// Create the FT View Data
875 ///
876 access(all)
877 fun createEditableFTView(
878 _ address: Address,
879 _ contractName: String,
880 _ storagePath: StoragePath,
881 ): @EditableFTView {
882 return <- create EditableFTView(address, contractName, storagePath)
883 }
884
885 /// Build the FT Vault Type
886 ///
887 access(all)
888 view fun buildFTVaultType(_ address: Address, _ contractName: String): Type? {
889 let addrStr = address.toString()
890 let addrStrNo0x = addrStr.slice(from: 2, upTo: addrStr.length)
891 return CompositeType("A.".concat(addrStrNo0x).concat(".").concat(contractName).concat(".Vault"))
892 }
893}
894