Smart Contract
FungibleTokenMetadataViews
A.f233dcee88fe0abe.FungibleTokenMetadataViews
1import FungibleToken from 0xf233dcee88fe0abe
2import MetadataViews from 0x1d7e57aa55817448
3import ViewResolver from 0x1d7e57aa55817448
4
5/// This contract implements the metadata standard proposed
6/// in FLIP-1087.
7///
8/// Ref: https://github.com/onflow/flips/blob/main/application/20220811-fungible-tokens-metadata.md
9///
10/// Structs and resources can implement one or more
11/// metadata types, called views. Each view type represents
12/// a different kind of metadata.
13///
14access(all) contract FungibleTokenMetadataViews {
15
16 /// FTView wraps FTDisplay and FTVaultData, and is used to give a complete
17 /// picture of a Fungible Token. Most Fungible Token contracts should
18 /// implement this view.
19 ///
20 access(all) struct FTView {
21 access(all) let ftDisplay: FTDisplay?
22 access(all) let ftVaultData: FTVaultData?
23 view init(
24 ftDisplay: FTDisplay?,
25 ftVaultData: FTVaultData?
26 ) {
27 self.ftDisplay = ftDisplay
28 self.ftVaultData = ftVaultData
29 }
30 }
31
32 /// Helper to get a FT view.
33 ///
34 /// @param viewResolver: A reference to the resolver resource
35 /// @return A FTView struct
36 ///
37 access(all) fun getFTView(viewResolver: &{ViewResolver.Resolver}): FTView {
38 let maybeFTView = viewResolver.resolveView(Type<FTView>())
39 if let ftView = maybeFTView {
40 return ftView as! FTView
41 }
42 return FTView(
43 ftDisplay: self.getFTDisplay(viewResolver),
44 ftVaultData: self.getFTVaultData(viewResolver)
45 )
46 }
47
48 /// View to expose the information needed to showcase this FT.
49 /// This can be used by applications to give an overview and
50 /// graphics of the FT.
51 ///
52 access(all) struct FTDisplay {
53 /// The display name for this token.
54 ///
55 /// Example: "Flow"
56 ///
57 access(all) let name: String
58
59 /// The abbreviated symbol for this token.
60 ///
61 /// Example: "FLOW"
62 access(all) let symbol: String
63
64 /// A description the provides an overview of this token.
65 ///
66 /// Example: "The FLOW token is the native currency of the Flow network."
67 access(all) let description: String
68
69 /// External link to a URL to view more information about the fungible token.
70 access(all) let externalURL: MetadataViews.ExternalURL
71
72 /// One or more versions of the fungible token logo.
73 access(all) let logos: MetadataViews.Medias
74
75 /// Social links to reach the fungible token's social homepages.
76 /// Possible keys may be "instagram", "twitter", "discord", etc.
77 access(all) let socials: {String: MetadataViews.ExternalURL}
78
79 view init(
80 name: String,
81 symbol: String,
82 description: String,
83 externalURL: MetadataViews.ExternalURL,
84 logos: MetadataViews.Medias,
85 socials: {String: MetadataViews.ExternalURL}
86 ) {
87 self.name = name
88 self.symbol = symbol
89 self.description = description
90 self.externalURL = externalURL
91 self.logos = logos
92 self.socials = socials
93 }
94 }
95
96 /// Helper to get FTDisplay in a way that will return a typed optional.
97 ///
98 /// @param viewResolver: A reference to the resolver resource
99 /// @return An optional FTDisplay struct
100 ///
101 access(all) fun getFTDisplay(_ viewResolver: &{ViewResolver.Resolver}): FTDisplay? {
102 if let maybeDisplayView = viewResolver.resolveView(Type<FTDisplay>()) {
103 if let displayView = maybeDisplayView as? FTDisplay {
104 return displayView
105 }
106 }
107 return nil
108 }
109
110 /// View to expose the information needed store and interact with a FT vault.
111 /// This can be used by applications to setup a FT vault with proper
112 /// storage and public capabilities.
113 ///
114 access(all) struct FTVaultData {
115 /// Path in storage where this FT vault is recommended to be stored.
116 access(all) let storagePath: StoragePath
117
118 /// Public path which must be linked to expose the public receiver capability.
119 access(all) let receiverPath: PublicPath
120
121 /// Public path which must be linked to expose the balance and resolver public capabilities.
122 access(all) let metadataPath: PublicPath
123
124 /// Type that should be linked at the `receiverPath`. This is a restricted type requiring
125 /// the `FungibleToken.Receiver` interface.
126 access(all) let receiverLinkedType: Type
127
128 /// Type that should be linked at the `receiverPath`. This is a restricted type requiring
129 /// the `ViewResolver.Resolver` interfaces.
130 access(all) let metadataLinkedType: Type
131
132 /// Function that allows creation of an empty FT vault that is intended
133 /// to store the funds.
134 access(all) let createEmptyVault: fun(): @{FungibleToken.Vault}
135
136 view init(
137 storagePath: StoragePath,
138 receiverPath: PublicPath,
139 metadataPath: PublicPath,
140 receiverLinkedType: Type,
141 metadataLinkedType: Type,
142 createEmptyVaultFunction: fun(): @{FungibleToken.Vault}
143 ) {
144 pre {
145 receiverLinkedType.isSubtype(of: Type<&{FungibleToken.Receiver}>()):
146 "Receiver public type <".concat(receiverLinkedType.identifier)
147 .concat("> must be a subtype of <").concat(Type<&{FungibleToken.Receiver}>().identifier)
148 .concat(">.")
149 metadataLinkedType.isSubtype(of: Type<&{FungibleToken.Vault}>()):
150 "Metadata linked type <".concat(metadataLinkedType.identifier)
151 .concat("> must be a subtype of <").concat(Type<&{FungibleToken.Vault}>().identifier)
152 .concat(">.")
153 }
154 self.storagePath = storagePath
155 self.receiverPath = receiverPath
156 self.metadataPath = metadataPath
157 self.receiverLinkedType = receiverLinkedType
158 self.metadataLinkedType = metadataLinkedType
159 self.createEmptyVault = createEmptyVaultFunction
160 }
161 }
162
163 /// Helper to get FTVaultData in a way that will return a typed Optional.
164 ///
165 /// @param viewResolver: A reference to the resolver resource
166 /// @return A optional FTVaultData struct
167 ///
168 access(all) fun getFTVaultData(_ viewResolver: &{ViewResolver.Resolver}): FTVaultData? {
169 if let view = viewResolver.resolveView(Type<FTVaultData>()) {
170 if let v = view as? FTVaultData {
171 return v
172 }
173 }
174 return nil
175 }
176
177 /// View to expose the total supply of the Vault's token
178 access(all) struct TotalSupply {
179 access(all) let supply: UFix64
180
181 view init(totalSupply: UFix64) {
182 self.supply = totalSupply
183 }
184 }
185}
186