Cadence Cookbook

Contribute

Creating a Set in Series

Creating a Set in Series

01 Apr 2022

Contributed by Flow Blockchain

Intermediate

Once you've implemented a series for your NFT, you now create Sets so that each NFT is part of a set in a series.

Smart Contract Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 // Variable size dictionary of SetData structs access(self) var setData: {UInt32: NFTSetData} pub struct NFTSetData { // Unique ID for the Set pub let setId: UInt32 // Series ID the Set belongs to pub let seriesId: UInt32 // Maximum number of editions that can be minted in this Set pub let maxEditions: UInt32 // The JSON metadata for each NFT edition can be stored off-chain on IPFS. // This is an optional dictionary of IPFS hashes, which will allow marketplaces // to pull the metadata for each NFT edition access(self) var ipfsMetadataHashes: {UInt32: String} // Set level metadata // Dictionary of metadata key value pairs access(self) var metadata: {String: String} init( setId: UInt32, seriesId: UInt32, maxEditions: UInt32, ipfsMetadataHashes: {UInt32: String}, metadata: {String: String}) { self.setId = setId self.seriesId = seriesId self.maxEditions = maxEditions self.metadata = metadata self.ipfsMetadataHashes = ipfsMetadataHashes emit SetCreated(seriesId: self.seriesId, setId: self.setId) } pub fun getIpfsMetadataHash(editionNum: UInt32): String? { return self.ipfsMetadataHashes[editionNum] } pub fun getMetadata(): {String: String} { return self.metadata } pub fun getMetadataField(field: String): String? { return self.metadata[field] } } .... // Resource that allows an admin to mint new NFTs // pub resource Series { // Unique ID for the Series pub let seriesId: UInt32 // Array of NFTSets that belong to this Series access(self) var setIds: [UInt32] // Series sealed state pub var seriesSealedState: Bool; // Set sealed state access(self) var setSealedState: {UInt32: Bool}; // Current number of editions minted per Set access(self) var numberEditionsMintedPerSet: {UInt32: UInt32} init( seriesId: UInt32, metadata: {String: String}) { self.seriesId = seriesId self.seriesSealedState = false self.numberEditionsMintedPerSet = {} self.setIds = [] self.setSealedState = {} SetAndSeries.seriesData[seriesId] = SeriesData( seriesId: seriesId, metadata: metadata ) } pub fun addNftSet( setId: UInt32, maxEditions: UInt32, ipfsMetadataHashes: {UInt32: String}, metadata: {String: String}) { pre { self.setIds.contains(setId) == false: "The Set has already been added to the Series." } // Create the new Set struct var newNFTSet = NFTSetData( setId: setId, seriesId: self.seriesId, maxEditions: maxEditions, ipfsMetadataHashes: ipfsMetadataHashes, metadata: metadata ) // Add the NFTSet to the array of Sets self.setIds.append(setId) // Initialize the NFT edition count to zero self.numberEditionsMintedPerSet[setId] = 0 // Store it in the sets mapping field SetAndSeries.setData[setId] = newNFTSet emit SetCreated(seriesId: self.seriesId, setId: setId) } .... //rest of code below }

Similarly to how you had created and assigned variables for a Series and SeriesData, you do the same for setData so that each set is managed correctly and you don't create the same set.

Afterwards you would create a struct for the NFT Set Data that would lay out all the variables you need for a set and what you need to do to initialize it.

Then you would have your series resource that would only exist in your account if you had used the admin account to create a new series. Once that series is created you have the availability to access the addNftSet function to create a new set.

Here you would enter in all the necessary parameters that go into creating an NFT Set. Once that's taken in you first check to make sure that the series doesn't already contain that setId.

If that is true then you establish the new NFTSetData struct. Afterwards you add the setId to the setId's array. Then you initialize the number of NFTS minted to 0 based on your setID # in the series because you are creating a brand new set.

Afterwards you store the setId and the NFTSetData struct in the setData dictionary where all the sets are able to be tracked.

Transaction Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import SetAndSeries from 0x01 transaction { let adminCheck: &SetAndSeries.Admin let seriesRef: &SetAndSeries.Series prepare(acct: AuthAccount) { self.adminCheck = acct.borrow<&SetAndSeries.Admin>(from: SetAndSeries.AdminStoragePath) ?? panic("could not borrow admin reference") self.seriesRef = self.adminCheck.borrowSeries(seriesId: 1) } execute { self.seriesRef.addNftSet(setId: 1, maxEditions: 5, ipfsMetadataHashes: {}, metadata: {"Rookie": "2004"}) log("set added") } }

Here you execute a transaction to create a new set. First you borrow a reference to the admin resource from the AuthAccount and afterwards you use the admin account to access the borrowSeries function.

Once that happens you are able to get access to the series you input in the parameters if it exists. After that you have access the addNftSet function to add as many sets as you would like.


ProgressNFT Fundamentals

Up Next: Minting NFTs in a Set

62%


Related Recipes

14 Oct 2022
Mint NFT
Beginner
14 Oct 2022
Collection for Holding NFTs
Beginner
14 Oct 2022
NFT with Metadata
Beginner