Skip to main content

NFT Catalog

info

The NFT Catalog is in the process of being deprecated. You can still use it for existing collections in the Catalog, but no new collections will be added from now on. Most of the functionality that the Catalog provided is now required and handled by default by the NonFungibleToken standard with Metadata Views.

Additionally, TokenList is a new permissionless tool that provides some of the old aggregation functionality that NFT Catalog provided without requiring approvals.

The NFT Catalog is an on chain registry listing NFT collections that exists on Flow which adhere to the NFT metadata standard. This empowers dApp developers to easily build on top of and discover interoperable NFT collections on Flow.

Live Site

Checkout the catalog site

Contract Addresses

NFTCatalog.cdc: This contract contains the NFT Catalog

NetworkAddress
Mainnet0x49a7cda3a1eecc29
Testnet0x324c34e1c517e4db

NFTRetrieval.cdc: This contract contains helper functions to make it easier to discover NFTs within accounts and from the catalog

NetworkAddress
Mainnet0x49a7cda3a1eecc29
Testnet0x324c34e1c517e4db

Using the Catalog (For marketplaces and other NFT applications)

All of the below examples use the catalog in mainnet, you may replace the imports to the testnet address when using the testnet network.

Example 1 - Retrieve all NFT collections on the catalog


_12
import NFTCatalog from 0x49a7cda3a1eecc29
_12
_12
/*
_12
The catalog is returned as a `String: NFTCatalogMetadata`
_12
The key string is intended to be a unique identifier for a specific collection.
_12
The NFTCatalogMetadata contains collection-level views corresponding to each
_12
collection identifier.
_12
*/
_12
access(all) fun main(): {String : NFTCatalog.NFTCatalogMetadata} {
_12
return NFTCatalog.getCatalog()
_12
_12
}

Example 2 - Retrieve all collection names in the catalog


_10
import NFTCatalog from 0x49a7cda3a1eecc29
_10
_10
access(all) fun main(): [String] {
_10
let catalog: {String : NFTCatalog.NFTCatalogMetadata} = NFTCatalog.getCatalog()
_10
let catalogNames: [String] = []
_10
for collectionIdentifier in catalog.keys {
_10
catalogNames.append(catalog[collectionIdentifier]!.collectionDisplay.name)
_10
}
_10
return catalogNames
_10
}

Example 3 - Retrieve NFT collections and counts owned by an account


_29
import MetadataViews from 0x1d7e57aa55817448
_29
import NFTCatalog from 0x49a7cda3a1eecc29
_29
import NFTRetrieval from 0x49a7cda3a1eecc29
_29
_29
access(all) fun main(ownerAddress: Address) : {String : Number} {
_29
let catalog = NFTCatalog.getCatalog()
_29
let account = getAuthAccount(ownerAddress)
_29
let items : {String : Number} = {}
_29
_29
for key in catalog.keys {
_29
let value = catalog[key]!
_29
let tempPathStr = "catalog".concat(key)
_29
let tempPublicPath = PublicPath(identifier: tempPathStr)!
_29
account.link<&{MetadataViews.ResolverCollection}>(
_29
tempPublicPath,
_29
target: value.collectionData.storagePath
_29
)
_29
let collectionCap = account.capabilities.get<&{MetadataViews.ResolverCollection}>(tempPublicPath)
_29
if !collectionCap.check() {
_29
continue
_29
}
_29
let count = NFTRetrieval.getNFTCountFromCap(collectionIdentifier : key, collectionCap : collectionCap)
_29
if count != 0 {
_29
items[key] = count
_29
}
_29
}
_29
_29
return items
_29
}

Sample Response...


_10
{
_10
"schmoes_prelaunch_token": 1
_10
}

Example 4 - Retrieve all NFTs including metadata owned by an account


_116
import MetadataViews from 0x1d7e57aa55817448
_116
import NFTCatalog from 0x49a7cda3a1eecc29
_116
import NFTRetrieval from 0x49a7cda3a1eecc29
_116
_116
access(all) struct NFT {
_116
access(all) let id : UInt64
_116
access(all) let name : String
_116
access(all) let description : String
_116
access(all) let thumbnail : String
_116
access(all) let externalURL : String
_116
access(all) let storagePath : StoragePath
_116
access(all) let publicPath : PublicPath
_116
access(all) let privatePath: PrivatePath
_116
access(all) let publicLinkedType: Type
_116
access(all) let privateLinkedType: Type
_116
access(all) let collectionName : String
_116
access(all) let collectionDescription: String
_116
access(all) let collectionSquareImage : String
_116
access(all) let collectionBannerImage : String
_116
access(all) let royalties: [MetadataViews.Royalty]
_116
_116
init(
_116
id: UInt64,
_116
name : String,
_116
description : String,
_116
thumbnail : String,
_116
externalURL : String,
_116
storagePath : StoragePath,
_116
publicPath : PublicPath,
_116
privatePath : PrivatePath,
_116
publicLinkedType : Type,
_116
privateLinkedType : Type,
_116
collectionIdentifier: String,
_116
collectionName : String,
_116
collectionDescription : String,
_116
collectionSquareImage : String,
_116
collectionBannerImage : String,
_116
royalties : [MetadataViews.Royalty]
_116
) {
_116
self.id = id
_116
self.name = name
_116
self.description = description
_116
self.thumbnail = thumbnail
_116
self.externalURL = externalURL
_116
self.storagePath = storagePath
_116
self.publicPath = publicPath
_116
self.privatePath = privatePath
_116
self.publicLinkedType = publicLinkedType
_116
self.privateLinkedType = privateLinkedType
_116
self.collectionIdentifier = collectionIdentifier
_116
self.collectionName = collectionName
_116
self.collectionDescription = collectionDescription
_116
self.collectionSquareImage = collectionSquareImage
_116
self.collectionBannerImage = collectionBannerImage
_116
self.royalties = royalties
_116
}
_116
}
_116
_116
access(all) fun main(ownerAddress: Address) : { String : [NFT] } {
_116
let catalog = NFTCatalog.getCatalog()
_116
let account = getAuthAccount<auth(Capabilities) &Account>(ownerAddress)
_116
let items : [NFTRetrieval.BaseNFTViewsV1] = []
_116
_116
let data : {String : [NFT] } = {}
_116
_116
for key in catalog.keys {
_116
let value = catalog[key]!
_116
let tempPathStr = "catalog".concat(key)
_116
let tempPublicPath = PublicPath(identifier: tempPathStr)!
_116
let newCap = account.capabilities.issue<&{MetadataViews.ResolverCollection}>
_116
(value.collectionData.storagePath)
_116
account.capabilities.publish(newCap, tempPublicPath)
_116
_116
let collectionCap = account.capabilities.get<&{MetadataViews.ResolverCollection}>(tempPublicPath)
_116
if !collectionCap.check() {
_116
continue
_116
}
_116
let views = NFTRetrieval.getNFTViewsFromCap(collectionIdentifier : key, collectionCap : collectionCap)
_116
_116
let items : [NFT] = []
_116
for view in views {
_116
let displayView = view.display
_116
let externalURLView = view.externalURL
_116
let collectionDataView = view.collectionData
_116
let collectionDisplayView = view.collectionDisplay
_116
let royaltyView = view.royalties
_116
if (displayView == nil || externalURLView == nil || collectionDataView == nil || collectionDisplayView == nil || royaltyView == nil) {
_116
// This NFT does not have the proper views implemented. Skipping....
_116
continue
_116
}
_116
_116
items.append(
_116
NFT(
_116
id: view.id,
_116
name : displayView!.name,
_116
description : displayView!.description,
_116
thumbnail : displayView!.thumbnail.uri(),
_116
externalURL : externalURLView!.url,
_116
storagePath : collectionDataView!.storagePath,
_116
publicPath : collectionDataView!.publicPath,
_116
privatePath : collectionDataView!.providerPath,
_116
publicLinkedType : collectionDataView!.publicLinkedType,
_116
privateLinkedType : collectionDataView!.providerLinkedType,
_116
collectionIdentifier: key,
_116
collectionName : collectionDisplayView!.name,
_116
collectionDescription : collectionDisplayView!.description,
_116
collectionSquareImage : collectionDisplayView!.squareImage.file.uri(),
_116
collectionBannerImage : collectionDisplayView!.bannerImage.file.uri(),
_116
royalties : royaltyView!.getRoyalties()
_116
)
_116
)
_116
}
_116
data[key] = items
_116
}
_116
return data
_116
}

Sample Response...


_23
{
_23
"FlovatarComponent": [],
_23
"schmoes_prelaunch_token": [
_23
s.aa16be98aac20e8073f923261531cbbdfae1464f570f5be796b57cdc97656248.NFT(
_23
id: 1006,
_23
name: "Schmoes Pre Launch Token #1006",
_23
description: "",
_23
thumbnail: "https://gateway.pinata.cloud/ipfs/QmXQ1iBke5wjcjYG22ACVXsCvtMJKEkwFiMf96UChP8uJq",
_23
externalURL: "https://schmoes.io",
_23
storagePath: /storage/SchmoesPreLaunchTokenCollection,
_23
publicPath: /public/SchmoesPreLaunchTokenCollection,
_23
privatePath: /private/SchmoesPreLaunchTokenCollection,
_23
publicLinkedType: Type<&A.6c4fe48768523577.SchmoesPreLaunchToken.Collection{A.1d7e57aa55817448.NonFungibleToken.CollectionPublic,A. 1d7e57aa55817448.NonFungibleToken.Receiver,A.1d7e57aa55817448.MetadataViews.ResolverCollection}>(),
_23
privateLinkedType: Type<&A.6c4fe48768523577.SchmoesPreLaunchToken.Collection{A.1d7e57aa55817448.NonFungibleToken.CollectionPublic,A.1d7e57aa55817448.NonFungibleToken.Provider,A.1d7e57aa55817448.MetadataViews.ResolverCollection}>(),
_23
collectionName: "Schmoes Pre Launch Token",
_23
collectionDescription: "",
_23
collectionSquareImage: "https://gateway.pinata.cloud/ipfs/QmXQ1iBke5wjcjYG22ACVXsCvtMJKEkwFiMf96UChP8uJq",
_23
collectionBannerImage: "https://gateway.pinata.cloud/ipfs/QmXQ1iBke5wjcjYG22ACVXsCvtMJKEkwFiMf96UChP8uJq",
_23
royalties: []
_23
)
_23
],
_23
"Flovatar": []
_23
}

Example 5 - Retrieve all NFTs including metadata owned by an account for large wallets

For Wallets that have a lot of NFTs you may run into memory issues. The common pattern to get around this for now is to retrieve just the ID's in a wallet by calling the following script


_32
import MetadataViews from 0x1d7e57aa55817448
_32
import NFTCatalog from 0x49a7cda3a1eecc29
_32
import NFTRetrieval from 0x49a7cda3a1eecc29
_32
_32
access(all) fun main(ownerAddress: Address) : {String : [UInt64]} {
_32
let catalog = NFTCatalog.getCatalog()
_32
let account = getAuthAccount<auth(Capabilities) &Account>(ownerAddress)
_32
_32
let items : {String : [UInt64]} = {}
_32
_32
for key in catalog.keys {
_32
let value = catalog[key]!
_32
let tempPathStr = "catalogIDs".concat(key)
_32
let tempPublicPath = PublicPath(identifier: tempPathStr)!
_32
let newCap = account.capabilities.issue<&{MetadataViews.ResolverCollection}>
_32
(value.collectionData.storagePath)
_32
account.capabilities.publish(newCap, tempPublicPath)
_32
_32
let collectionCap = account.capabilities.get<&{MetadataViews.ResolverCollection}>(tempPublicPath)
_32
if !collectionCap.check() {
_32
continue
_32
}
_32
_32
let ids = NFTRetrieval.getNFTIDsFromCap(collectionIdentifier : key, collectionCap : collectionCap)
_32
_32
if ids.length > 0 {
_32
items[key] = ids
_32
}
_32
}
_32
return items
_32
_32
}

and then use the ids to retrieve the full metadata for only those ids by calling the following script and passing in a map of collectlionIdentifer -> [ids]


_119
import MetadataViews from 0x1d7e57aa55817448
_119
import NFTCatalog from 0x49a7cda3a1eecc29
_119
import NFTRetrieval from 0x49a7cda3a1eecc29
_119
_119
access(all) struct NFT {
_119
access(all) let id : UInt64
_119
access(all) let name : String
_119
access(all) let description : String
_119
access(all) let thumbnail : String
_119
access(all) let externalURL : String
_119
access(all) let storagePath : StoragePath
_119
access(all) let publicPath : PublicPath
_119
access(all) let privatePath: PrivatePath
_119
access(all) let publicLinkedType: Type
_119
access(all) let privateLinkedType: Type
_119
access(all) let collectionName : String
_119
access(all) let collectionDescription: String
_119
access(all) let collectionSquareImage : String
_119
access(all) let collectionBannerImage : String
_119
access(all) let royalties: [MetadataViews.Royalty]
_119
_119
init(
_119
id: UInt64,
_119
name : String,
_119
description : String,
_119
thumbnail : String,
_119
externalURL : String,
_119
storagePath : StoragePath,
_119
publicPath : PublicPath,
_119
privatePath : PrivatePath,
_119
publicLinkedType : Type,
_119
privateLinkedType : Type,
_119
collectionName : String,
_119
collectionDescription : String,
_119
collectionSquareImage : String,
_119
collectionBannerImage : String,
_119
royalties : [MetadataViews.Royalty]
_119
) {
_119
self.id = id
_119
self.name = name
_119
self.description = description
_119
self.thumbnail = thumbnail
_119
self.externalURL = externalURL
_119
self.storagePath = storagePath
_119
self.publicPath = publicPath
_119
self.privatePath = privatePath
_119
self.publicLinkedType = publicLinkedType
_119
self.privateLinkedType = privateLinkedType
_119
self.collectionName = collectionName
_119
self.collectionDescription = collectionDescription
_119
self.collectionSquareImage = collectionSquareImage
_119
self.collectionBannerImage = collectionBannerImage
_119
self.royalties = royalties
_119
}
_119
}
_119
_119
access(all) fun main(ownerAddress: Address, collections: {String : [UInt64]}) : {String : [NFT] } {
_119
let data : {String : [NFT] } = {}
_119
_119
let catalog = NFTCatalog.getCatalog()
_119
let account = getAuthAccount<auth(Capabilities) &Account>(ownerAddress)
_119
for collectionIdentifier in collections.keys {
_119
if catalog.containsKey(collectionIdentifier) {
_119
let value = catalog[collectionIdentifier]!
_119
let tempPathStr = "catalog".concat(collectionIdentifier)
_119
let tempPublicPath = PublicPath(identifier: tempPathStr)!
_119
let newCap = account.capabilities.issue<&{MetadataViews.ResolverCollection}>
_119
(value.collectionData.storagePath)
_119
account.capabilities.publish(newCap, tempPublicPath)
_119
_119
let collectionCap = account.capabilities.get<&{MetadataViews.ResolverCollection}>(tempPublicPath)
_119
_119
if !collectionCap.check() {
_119
return data
_119
}
_119
_119
let views = NFTRetrieval.getNFTViewsFromIDs(collectionIdentifier : collectionIdentifier, ids: collections[collectionIdentifier]!, collectionCap : collectionCap)
_119
_119
let items : [NFT] = []
_119
_119
for view in views {
_119
let displayView = view.display
_119
let externalURLView = view.externalURL
_119
let collectionDataView = view.collectionData
_119
let collectionDisplayView = view.collectionDisplay
_119
let royaltyView = view.royalties
_119
if (displayView == nil || externalURLView == nil || collectionDataView == nil || collectionDisplayView == nil || royaltyView == nil) {
_119
// Bad NFT. Skipping....
_119
continue
_119
}
_119
_119
items.append(
_119
NFT(
_119
id: view.id,
_119
name : displayView!.name,
_119
description : displayView!.description,
_119
thumbnail : displayView!.thumbnail.uri(),
_119
externalURL : externalURLView!.url,
_119
storagePath : collectionDataView!.storagePath,
_119
publicPath : collectionDataView!.publicPath,
_119
privatePath : collectionDataView!.providerPath,
_119
publicLinkedType : collectionDataView!.publicLinkedType,
_119
privateLinkedType : collectionDataView!.providerLinkedType,
_119
collectionName : collectionDisplayView!.name,
_119
collectionDescription : collectionDisplayView!.description,
_119
collectionSquareImage : collectionDisplayView!.squareImage.file.uri(),
_119
collectionBannerImage : collectionDisplayView!.bannerImage.file.uri(),
_119
royalties : royaltyView!.getRoyalties()
_119
)
_119
)
_119
}
_119
_119
data[collectionIdentifier] = items
_119
}
_119
}
_119
_119
_119
return data
_119
}

Example 6 - Retrieve all MetadataViews for NFTs in a wallet

If you're looking for some MetadataViews that aren't in the core view list you can leverage this script to grab all the views each NFT supports. Note: You lose some typing here but get more data.


_59
import MetadataViews from 0x1d7e57aa55817448
_59
import NFTCatalog from 0x49a7cda3a1eecc29
_59
import NFTRetrieval from 0x49a7cda3a1eecc29
_59
_59
access(all) struct NFTCollectionData {
_59
access(all) let storagePath : StoragePath
_59
access(all) let publicPath : PublicPath
_59
access(all) let publicLinkedType: Type
_59
_59
init(
_59
storagePath : StoragePath,
_59
publicPath : PublicPath,
_59
publicLinkedType : Type,
_59
) {
_59
self.storagePath = storagePath
_59
self.publicPath = publicPath
_59
self.publicLinkedType = publicLinkedType
_59
}
_59
}
_59
_59
access(all) fun main(ownerAddress: Address) : { String : {String : AnyStruct} } {
_59
let catalog = NFTCatalog.getCatalog()
_59
let account = getAuthAccount<auth(Capabilities) &Account>(ownerAddress)
_59
let items : [MetadataViews.NFTView] = []
_59
_59
let data : { String : {String : AnyStruct} } = {}
_59
_59
for key in catalog.keys {
_59
let value = catalog[key]!
_59
let tempPathStr = "catalog".concat(key)
_59
let tempPublicPath = PublicPath(identifier: tempPathStr)!
_59
let newCap = account.capabilities.issue<&{MetadataViews.ResolverCollection}>
_59
(value.collectionData.storagePath)
_59
account.capabilities.publish(newCap, tempPublicPath)
_59
let collectionCap = account.capabilities.get<&{MetadataViews.ResolverCollection}>(tempPublicPath)
_59
if !collectionCap.check() {
_59
continue
_59
}
_59
_59
var views = NFTRetrieval.getAllMetadataViewsFromCap(collectionIdentifier : key, collectionCap : collectionCap)
_59
_59
if views.keys.length == 0 {
_59
continue
_59
}
_59
_59
// Cadence doesn't support function return types, lets manually get rid of it
_59
let nftCollectionDisplayView = views[Type<MetadataViews.NFTCollectionData>().identifier] as! MetadataViews.NFTCollectionData?
_59
let collectionDataView = NFTCollectionData(
_59
storagePath : nftCollectionDisplayView!.storagePath,
_59
publicPath : nftCollectionDisplayView!.publicPath,
_59
publicLinkedType : nftCollectionDisplayView!.publicLinkedType,
_59
)
_59
views.insert(key: Type<MetadataViews.NFTCollectionData>().identifier, collectionDataView)
_59
_59
data[key] = views
_59
}
_59
_59
return data
_59
}

Example 7 - Setup a user’s account to receive a specific collection

  1. Run the following script to retrieve some collection-level information for an NFT collection identifier from the catalog

_58
import MetadataViews from 0x1d7e57aa55817448
_58
import NFTCatalog from 0x49a7cda3a1eecc29
_58
import NFTRetrieval from 0x49a7cda3a1eecc29
_58
_58
access(all) struct NFTCollection {
_58
access(all) let storagePath : StoragePath
_58
access(all) let publicPath : PublicPath
_58
access(all) let privatePath: PrivatePath
_58
access(all) let publicLinkedType: Type
_58
access(all) let privateLinkedType: Type
_58
access(all) let collectionName : String
_58
access(all) let collectionDescription: String
_58
access(all) let collectionSquareImage : String
_58
access(all) let collectionBannerImage : String
_58
_58
init(
_58
storagePath : StoragePath,
_58
publicPath : PublicPath,
_58
privatePath : PrivatePath,
_58
publicLinkedType : Type,
_58
privateLinkedType : Type,
_58
collectionName : String,
_58
collectionDescription : String,
_58
collectionSquareImage : String,
_58
collectionBannerImage : String
_58
) {
_58
self.storagePath = storagePath
_58
self.publicPath = publicPath
_58
self.privatePath = privatePath
_58
self.publicLinkedType = publicLinkedType
_58
self.privateLinkedType = privateLinkedType
_58
self.collectionName = collectionName
_58
self.collectionDescription = collectionDescription
_58
self.collectionSquareImage = collectionSquareImage
_58
self.collectionBannerImage = collectionBannerImage
_58
}
_58
}
_58
_58
access(all) fun main(collectionIdentifier : String) : NFT? {
_58
let catalog = NFTCatalog.getCatalog()
_58
_58
assert(catalog.containsKey(collectionIdentifier), message: "Invalid Collection")
_58
_58
return NFTCollection(
_58
storagePath : collectionDataView!.storagePath,
_58
publicPath : collectionDataView!.publicPath,
_58
privatePath : collectionDataView!.providerPath,
_58
publicLinkedType : collectionDataView!.publicLinkedType,
_58
privateLinkedType : collectionDataView!.providerLinkedType,
_58
collectionName : collectionDisplayView!.name,
_58
collectionDescription : collectionDisplayView!.description,
_58
collectionSquareImage : collectionDisplayView!.squareImage.file.uri(),
_58
collectionBannerImage : collectionDisplayView!.bannerImage.file.uri()
_58
)
_58
}
_58
_58
panic("Invalid Token ID")
_58
}

  1. This script result can then be used to form a transaction by inserting the relevant variables from above into a transaction template like the following:

_28
import NonFungibleToken from 0x1d7e57aa55817448
_28
import MetadataViews from 0x1d7e57aa55817448
_28
{ADDITIONAL_IMPORTS}
_28
_28
transaction {
_28
_28
prepare(signer: auth(BorrowValue, IssueStorageCapabilityController, PublishCapability, SaveValue, UnpublishCapability) &Account) {
_28
_28
let collectionData = {CONTRACT_NAME}.resolveContractView(resourceType: nil, viewType: Type<MetadataViews.NFTCollectionData>()) as! MetadataViews.NFTCollectionData?
_28
?? panic("Could not resolve NFTCollectionData view. The {CONTRACT_NAME} contract needs to implement the NFTCollectionData Metadata view in order to execute this transaction")
_28
_28
// Return early if the account already has a collection
_28
if signer.storage.borrow<&{CONTRACT_NAME}.Collection>(from: collectionData.storagePath) != nil {
_28
return
_28
}
_28
_28
// Create a new empty collection
_28
let collection <- {CONTRACT_NAME}.createEmptyCollection(nftType: Type<@{CONTRACT_NAME}.NFT>())
_28
_28
// save it to the account
_28
signer.storage.save(<-collection, to: collectionData.storagePath)
_28
_28
// create a public capability for the collection
_28
signer.capabilities.unpublish(collectionData.publicPath)
_28
let collectionCap = signer.capabilities.storage.issue<&{CONTRACT_NAME}.Collection>(collectionData.storagePath)
_28
signer.capabilities.publish(collectionCap, at: collectionData.publicPath)
_28
}
_28
}

An even easier way to setup an account without relying on the NFT Catalog is to just use the generic setup account transaction. All you need is the name and address of the contract!


_37
import "NonFungibleToken"
_37
import "MetadataViews"
_37
_37
/// This transaction is what an account would run
_37
/// to set itself up to receive NFTs. This function
_37
/// uses views to know where to set up the collection
_37
/// in storage and to create the empty collection.
_37
///
_37
/// @param contractAddress: The address of the contract that defines the token being initialized
_37
/// @param contractName: The name of the contract that defines the token being initialized. Ex: "ExampleNFT"
_37
_37
transaction(contractAddress: Address, contractName: String) {
_37
_37
prepare(signer: auth(IssueStorageCapabilityController, PublishCapability, SaveValue) &Account) {
_37
// Borrow a reference to the nft contract deployed to the passed account
_37
let resolverRef = getAccount(contractAddress)
_37
.contracts.borrow<&{NonFungibleToken}>(name: contractName)
_37
?? panic("Could not borrow NonFungibleToken reference to the contract. Make sure the provided contract name ("
_37
.concat(contractName).concat(") and address (").concat(contractAddress.toString()).concat(") are correct!"))
_37
_37
// Use that reference to retrieve the NFTCollectionData view
_37
let collectionData = resolverRef.resolveContractView(resourceType: nil, viewType: Type<MetadataViews.NFTCollectionData>()) as! MetadataViews.NFTCollectionData?
_37
?? panic("Could not resolve NFTCollectionData view. The ".concat(contractName).concat(" contract needs to implement the NFTCollectionData Metadata view in order to execute this transaction"))
_37
_37
// Create a new empty collections
_37
let emptyCollection <- collectionData.createEmptyCollection()
_37
_37
// save it to the account
_37
signer.storage.save(<-emptyCollection, to: collectionData.storagePath)
_37
_37
// create a public capability for the collection
_37
let collectionCap = signer.capabilities.storage.issue<&{NonFungibleToken.Collection}>(
_37
collectionData.storagePath
_37
)
_37
signer.capabilities.publish(collectionCap, at: collectionData.publicPath)
_37
}
_37
}

Developer Usage

1. Install the Flow CLI

2. Install Node

3. Clone the project


_10
git clone --depth=1 https://github.com/onflow/nft-catalog.git

4. Install packages

  • Run npm install in the root of the project

5. Run Test Suite

  • Run npm test in the root of the project

Cadence Generation

Using the NFT Catalog, you can generate common scripts and transactions to be run against the Flow Blockchain to support your application.

Generate from Javascript

Installation


_10
npm install @onflow/fcl
_10
npm install flow-catalog

or


_10
yarn add @onflow/fcl
_10
yarn add flow-catalog

Usage

1. Retrieve a list of transactions available for code generation: NOTE: In order to properly bootstrap the method, you will need to run and await on the getAddressMaps() method, passing it into all of the methods as shown below.


_10
import { getAddressMaps, scripts } from "flow-catalog";
_10
import * as fcl from "@onflow/fcl"
_10
_10
const main = async () => {
_10
const addressMap = await getAddressMaps();
_10
console.log(await scripts.getSupportedGeneratedTransactions(addressMap));
_10
};
_10
_10
main();

2. Provide a Catalog collection identifier to generate code


_15
const getTemplatedTransactionCode = async function() {
_15
const catalogAddressMap = await getAddressMaps()
_15
const result = await cadence.scripts.genTx({
_15
_15
/*
_15
'CollectionInitialization' is one of the available transactions from step 1.
_15
'Flunks' is the collection identifier in this case
_15
'Flow' is a fungible token identifier (if applicable to the transaction being used)
_15
*/
_15
_15
args: ['CollectionInitialization', 'Flunks', 'flow'],
_15
addressMap: catalogAddressMap
_15
})
_15
return result
_15
}

3. Use the generated code in a transaction


_10
const txId = await fcl.mutate({
_10
cadence: await getTemplatedTransactionCode()[0],
_10
limit: 9999,
_10
args: (arg: any, t: any) => []
_10
});
_10
const transaction = await fcl.tx(txId).onceSealed()
_10
return transaction

Generate from non-Javascript environments

Cadence scripts and transactions can be generated directly on-chain via scripts. You will need to be able to run cadence scripts to continue.

1. Retrieve a list of transactions available for code generation

Run the following script to retrieve available code generation methods: https://github.com/dapperlabs/nft-catalog/blob/main/cadence/scripts/get_supported_generated_transactions.cdc

2. Provide a catalog collection identifier to generate code

You may use the following script to generate code: https://github.com/dapperlabs/nft-catalog/blob/main/cadence/scripts/gen_tx.cdc

For example, from the CLI this may be run like the following: flow -n mainnet scripts execute ./get_tx.cdc CollectionInitialization Flunks flow

In the above example, CollectionInitialization is one of the supported transactions returned from step 1, Flunks is the name of an entry on the catalog (https://www.flow-nft-catalog.com/catalog/mainnet/Flunks), and flow is a fungible token identifier.

NPM Module

We exposed an interface to the catalog via a consumable NPM module. This library will expose a number of methods that can be called to interact with the catalog.

Methods

Method signatures and their associating parameters/responses can be found in the cadence/ folder of this repo.

Scripts


_20
checkForRecommendedV1Views
_20
genTx
_20
getAllNftsInAccount
_20
getExamplenftCollectionLength
_20
getExamplenftType
_20
getNftCatalog
_20
getNftCatalogProposals
_20
getNftCollectionsForNftType
_20
getNftIdsInAccount
_20
getNftInAccount
_20
getNftInAccountFromPath
_20
getNftMetadataForCollectionIdentifier
_20
getNftProposalForId
_20
getNftsCountInAccount
_20
getNftsInAccount
_20
getNftsInAccountFromIds
_20
getNftsInAccountFromPath
_20
getSupportedGeneratedTransactions
_20
hasAdminProxy
_20
isCatalogAdmin

Transactions


_17
addToNftCatalog
_17
addToNftCatalogAdmin
_17
approveNftCatalogProposal
_17
mintExampleNft
_17
mintNonstandardNft
_17
proposeNftToCatalog
_17
rejectNftCatalogProposal
_17
removeFromNftCatalog
_17
removeNftCatalogProposal
_17
sendAdminCapabilityToProxy
_17
setupExamplenftCollection
_17
setupNftCatalogAdminProxy
_17
setupNonstandardnftCollection
_17
setupStorefront
_17
transferExamplenft
_17
updateNftCatalogEntry
_17
withdrawNftProposalFromCatalog

Installation


_10
npm install flow-catalog

or


_10
yarn add flow-catalog

Usage

Methods can be imported as follows, all nested methods live under the scripts or transactions variable.

NOTE: In order to properly bootstrap the method, you will need to run and await on the getAddressMaps() method, passing it into all of the methods as shown below.


_10
import { getAddressMaps, scripts } from "flow-catalog";
_10
_10
const main = async () => {
_10
const addressMap = await getAddressMaps();
_10
console.log(await scripts.getNftCatalog(addressMap));
_10
};
_10
_10
main();

The response of any method is a tuple-array, with the first element being the result, and the second being the error (if applicable).

For example, the result of the method above would look like -


_20
[
_20
{
_20
BILPlayerCollection: {
_20
contractName: 'Player',
_20
contractAddress: '0x9e6cdb88e34fa1f3',
_20
nftType: [Object],
_20
collectionData: [Object],
_20
collectionDisplay: [Object]
_20
},
_20
...
_20
SoulMadeComponent: {
_20
contractName: 'SoulMadeComponent',
_20
contractAddress: '0x421c19b7dc122357',
_20
nftType: [Object],
_20
collectionData: [Object],
_20
collectionDisplay: [Object]
_20
}
_20
},
_20
null
_20
]

License

The works in these files:

are under the Unlicense.