NFT MetadataViews on Flow
MetadataViews
on Flow offer a standardized way to represent metadata across different NFTs. Through its integration, developers can ensure that different platforms and marketplaces can interpret the NFT metadata in a unified manner. This means that when users visit different websites, wallets, and marketplaces, the NFT metadata will be presented in a consistent manner, ensuring a uniform experience across various platforms.
If you'd like to follow along while we discuss the concepts below, you can do so by referring to the ExampleNFT contract. Additionally, here is the source code for the MetadataViews contract.
Two Levels of Metadata: An Overview
Metadata in Cadence is structured at two distinct levels:
- Contract-Level Metadata: This provides an overarching description of the entire NFT collection.
- NFT-Level Metadata: Diving deeper, this metadata relates to individual NFTs. It provides context, describes rarity, and highlights other distinctive attributes that distinguish one NFT from another within the same collection.
Understanding ViewResolver
and MetadataViews.Resolver
When considering Flow and how it handles metadata for NFTs, it's crucial to understand two essential interfaces: ViewResolver
and MetadataViews.Resolver
. Interfaces serve as blueprints that specify the required variables and methods that your contract must adhere to for the interface to be deemed properly implemented. This guarantees that any contract asserting adherence to these interfaces will possess a consistent set of functionalities that other applications or contracts can rely on.
ViewResolver
for Contract-Level Metadata:- This interface ensures that contracts, particularly those encapsulating NFT collections, conform to the Metadata Views standard.
- Through the adoption of this interface, contracts can provide dynamic metadata that represents the entirety of the collection.
MetadataViews.Resolver
for NFT-Level Metadata:- Used within individual NFT resources, this interface ensures each token adheres to the Metadata standard format.
- It focuses on the distinct attributes of an individual NFT, such as its unique ID, name, description, and other defining characteristics.
Core Functions
Both the ViewResolver
and MetadataViews.Resolver
utilize the following core functions:
getViews
Function
This function provides a list of supported metadata view types, which can be applied either by the contract (in the case of ViewResolver
) or by an individual NFT (in the case of MetadataViews.Resolver
).
_10pub fun getViews(): [Type] {_10 return [_10 Type<MetadataViews.Display>(),_10 ..._10 ]_10}
resolveView
Function
Whether utilized at the contract or NFT level, this function's role is to deliver the actual metadata associated with a given view type.
_10pub fun resolveView(_ view: Type): AnyStruct? {_10 switch view {_10 case Type<MetadataViews.Display>():_10 ..._10 ..._10 }_10 return nil_10}
NFT-Level Metadata Implementation
NFT-level metadata addresses the unique attributes of individual tokens within a collection. It provides structured information for each NFT, including its identifier, descriptive elements, royalties, and other associated metadata. Incorporating this level of detail ensures consistency and standardization among individual NFTs, making them interoperable and recognizable across various platforms and marketplaces.
Core Properties
For instance, in the code below, an NFT has properties such as its unique ID, name, description, and others. When we add the MetadataViews.Resolver
to our NFT resource, we are indicating that these variables will adhere to the specifications outlined in the MetadataViews contract for each of these properties. This facilitates interoperability within the Flow ecosystem and assures that the metadata of our NFT can be consistently accessed and understood by various platforms and services that interact with NFTs.
_10pub resource NFT: NonFungibleToken.INFT, MetadataViews.Resolver {_10 pub let id: UInt64_10 pub let name: String_10 pub let description: String_10 pub let thumbnail: String_10 access(self) let royalties: [MetadataViews.Royalty]_10 access(self) let metadata: {String: AnyStruct}_10 ..._10}
Metadata Views for NFTs
MetadataViews
types define how the NFT presents its data. When invoked, the system knows precisely which view to return, ensuring that the relevant information is presented consistently across various platforms:
Display
This view provides basic information about the NFT suitable for listing or display purposes. When the Display
type is invoked, it dynamically assembles the visual and descriptive information that is typically needed for showcasing the NFT in marketplaces or collections.
_10case Type<MetadataViews.Display>():_10 return MetadataViews.Display(_10 name: self.name,_10 description: self.description,_10 thumbnail: MetadataViews.HTTPFile(_10 url: self.thumbnail_10 )_10 )
Editions
The Editions
view provides intricate details regarding the particular release of an NFT. This can include information about the number of copies in an edition, the specific NFT's sequence number within that edition, or its inclusion in a limited series. When the Editions
view is queried, it retrieves this data, providing collectors with the information they need to comprehend the rarity and exclusivity of the NFT they are interested in.
_10case Type<MetadataViews.Editions>():_10 let editionInfo = MetadataViews.Edition(_10 name: "Example NFT Edition",_10 number: self.id,_10 max: nil_10 )_10 return MetadataViews.Editions([editionInfo])
Serial Number Metadata
The Serial
metadata provides the unique serial number of the NFT, akin to a serial number on a currency note or a VIN on a car. This serial number is a fundamental attribute that certifies the individuality of each NFT and is critical for identification and verification processes.
_10case Type<MetadataViews.Serial>():_10 return MetadataViews.Serial(self.id)
Royalties Metadata
Royalty information is vital for the sustainable economics of the creators in the NFT space. The Royalties
metadata view defines the specifics of any royalty agreements in place, including the percentage of sales revenue that will go to the original creator or other stakeholders on secondary sales.
_10case Type<MetadataViews.Royalties>():_10 // Assuming each 'Royalty' in the 'royalties' array has 'cut' and 'description' fields_10 let detailedRoyalties = self.royalties.map { royalty ->_10 MetadataViews.Royalty(_10 receiver: royalty.receiver, // The beneficiary of the royalty_10 cut: royalty.cut, // The percentage cut of each sale_10 description: royalty.description // A description of the royalty terms_10 )_10 }_10 return MetadataViews.Royalties(detailedRoyalties)
External URL Metadata
The ExternalURL view returns to an associated webpage URL, providing additional content or information about the NFT.
_10case Type<MetadataViews.ExternalURL>():_10 return MetadataViews.ExternalURL("<https://example-nft.onflow.org/>".concat(self.id.toString()))
Traits Metadata
Traits view type encapsulates the unique attributes of an NFT, like any visual aspects or category-defining properties. These can be essential for marketplaces that need to sort or filter NFTs based on these characteristics.
The dictToTraits
helper function in Cadence is designed to convert a dictionary of metadata into a standard array of Trait
structures. This function helps in preparing the traits data for the MetadataViews.Traits
view, which can be understood by platforms within the Flow ecosystem.
Here's a more detailed look at how you might implement the dictToTraits
function and the Traits
view:
_10case Type<MetadataViews.Traits>():_10 // Exclude certain traits from being displayed_10 let excludedTraits = ["mintedTime", "foo"]_10_10 // Convert the remaining metadata into an array of `Trait` objects_10 let traitsArray = MetadataViews.dictToTraits(dict: self.metadata, excludedNames: excludedTraits)_10_10 return traitsArray
Contract-Level Metadata Implementation
Contract-level metadata provides a holistic view of an NFT collection, capturing overarching attributes and contextual information about the entire set, rather than specifics of individual tokens. These views describe attributes at the collection or series level rather than individual NFTs.
NFTCollectionData
This view provides paths and types related to the NFT collection's storage and access within the smart contract.
_12case Type<MetadataViews.NFTCollectionData>():_12 return MetadataViews.NFTCollectionData(_12 storagePath: ExampleNFT.CollectionStoragePath,_12 publicPath: ExampleNFT.CollectionPublicPath,_12 providerPath: /private/exampleNFTCollection,_12 publicCollection: Type<&ExampleNFT.Collection{ExampleNFT.ExampleNFTCollectionPublic}>(),_12 publicLinkedType: Type<&ExampleNFT.Collection{ExampleNFT.ExampleNFTCollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Receiver,MetadataViews.ResolverCollection}>(),_12 providerLinkedType: Type<&ExampleNFT.Collection{ExampleNFT.ExampleNFTCollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Provider,MetadataViews.ResolverCollection}>(),_12 createEmptyCollectionFunction: (fun (): @NonFungibleToken.Collection {_12 return <-ExampleNFT.createEmptyCollection()_12 })_12 )
Here, NFTCollectionData
is specifying several important elements related to how the collection is stored and accessed on the Flow blockchain. It provides information on storage paths and access control paths for both public and private data, as well as linked types that specify what capabilities are publicly available (like collection, receiver, or provider interfaces).
NFTCollectionDisplay
This view describes the collection with visual elements and metadata that are useful for display purposes, such as in a marketplace or gallery.
_17case Type<MetadataViews.NFTCollectionDisplay>():_17 let media = MetadataViews.Media(_17 file: MetadataViews.HTTPFile(_17 url: "<https://assets.website-files.com/5f6294c0c7a8cdd643b1c820/5f6294c0c7a8cda55cb1c936_Flow_Wordmark.svg>"_17 ),_17 mediaType: "image/svg+xml"_17 )_17 return MetadataViews.NFTCollectionDisplay(_17 name: "The Example Collection",_17 description: "This collection is used as an example to help you develop your next Flow NFT.",_17 externalURL: MetadataViews.ExternalURL("<https://example-nft.onflow.org>"),_17 squareImage: media,_17 bannerImage: media,_17 socials: {_17 "twitter": MetadataViews.ExternalURL("<https://twitter.com/flow_blockchain>")_17 }_17 )
In the example above, the NFTCollectionDisplay
not only offers fundamental metadata like the collection's name and description but also provides image URLs for visual representations of the collection (squareImage
and bannerImage
) and external links, including social media profiles.
More
Understanding MetadataViews
and the core functions associated with it is crucial for developers aiming to deploy NFTs on Flow. With these views and functions, NFTs can maintain a consistent presentation across various platforms and marketplaces and foster interoperability between contracts and applications in the Flow ecosystem. To gain a deeper understanding of implementing the MetadataView standard, Check out our documentation on "How to Create an NFT Project on Flow". It provides an introduction to integrating these standards into your NFT contracts.
- See the API reference for a complete list of Metadata functions
- Check out an Example NFT project implementing
MetadataViews
- Read the NFT Guide for an introduction to implementation