Smart Contract

ChainzKey

A.ff342b6df9ef019d.ChainzKey

Deployed

2h ago
Feb 28, 2026, 06:37:35 PM UTC

Dependents

0 imports
1import NonFungibleToken from 0x1d7e57aa55817448
2import MetadataViews from 0x1d7e57aa55817448
3
4pub contract ChainzKey: NonFungibleToken {
5
6    pub var totalSupply: UInt64
7
8    pub event ContractInitialized()
9    pub event Withdraw(id: UInt64, from: Address?)
10    pub event Deposit(id: UInt64, to: Address?)
11
12    pub let CollectionStoragePath: StoragePath
13    pub let CollectionPublicPath: PublicPath
14    pub let MinterStoragePath: StoragePath
15
16    pub resource NFT: NonFungibleToken.INFT, MetadataViews.Resolver {
17        pub let id: UInt64
18        pub let tier: String
19        pub let type: String
20        pub let serial: UInt64
21        access(self) let metadata: {String: AnyStruct}
22    
23        init(
24            tier: String,
25            type: String,
26            serial: UInt64,
27            metadata: {String: AnyStruct},
28        ) {
29            self.id = self.uuid
30            self.serial = serial
31            self.type = type
32            self.tier = tier
33            self.metadata = metadata
34
35            ChainzKey.totalSupply = ChainzKey.totalSupply + 1
36        }
37    
38        pub fun getViews(): [Type] {
39            return [
40                Type<MetadataViews.Display>(),
41                Type<MetadataViews.Editions>(),
42                Type<MetadataViews.ExternalURL>(),
43                Type<MetadataViews.NFTCollectionData>(),
44                Type<MetadataViews.NFTCollectionDisplay>(),
45                Type<MetadataViews.Serial>(),
46                Type<MetadataViews.Traits>()
47            ]
48        }
49
50        pub fun resolveView(_ view: Type): AnyStruct? {
51            switch view {
52                case Type<MetadataViews.Display>():
53                    return MetadataViews.Display(
54                        name: "Chainz Key",
55                        description: "This is a Chainz Key NFT.",
56                        thumbnail: MetadataViews.HTTPFile(
57                            url: ""
58                        )
59                    )
60                case Type<MetadataViews.Editions>():
61                    // There is no max number of NFTs that can be minted from this contract
62                    // so the max edition field value is set to nil
63                    let editionInfo = MetadataViews.Edition(name: "Example NFT Edition", number: self.id, max: nil)
64                    let editionList: [MetadataViews.Edition] = [editionInfo]
65                    return MetadataViews.Editions(
66                        editionList
67                    )
68                case Type<MetadataViews.Serial>():
69                    return MetadataViews.Serial(
70                        self.id
71                    )
72                case Type<MetadataViews.ExternalURL>():
73                    return MetadataViews.ExternalURL("https://example-nft.onflow.org/".concat(self.id.toString()))
74                case Type<MetadataViews.NFTCollectionData>():
75                    return MetadataViews.NFTCollectionData(
76                        storagePath: ChainzKey.CollectionStoragePath,
77                        publicPath: ChainzKey.CollectionPublicPath,
78                        providerPath: /private/ChainzKeyCollection,
79                        publicCollection: Type<&ChainzKey.Collection{ChainzKey.CollectionPublic}>(),
80                        publicLinkedType: Type<&ChainzKey.Collection{ChainzKey.CollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Receiver,MetadataViews.ResolverCollection}>(),
81                        providerLinkedType: Type<&ChainzKey.Collection{ChainzKey.CollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Provider,MetadataViews.ResolverCollection}>(),
82                        createEmptyCollectionFunction: (fun (): @NonFungibleToken.Collection {
83                            return <-ChainzKey.createEmptyCollection()
84                        })
85                    )
86                case Type<MetadataViews.NFTCollectionDisplay>():
87                    let media = MetadataViews.Media(
88                        file: MetadataViews.HTTPFile(
89                            url: "https://assets.website-files.com/5f6294c0c7a8cdd643b1c820/5f6294c0c7a8cda55cb1c936_Flow_Wordmark.svg"
90                        ),
91                        mediaType: "image/svg+xml"
92                    )
93                    return MetadataViews.NFTCollectionDisplay(
94                        name: "The Example Collection",
95                        description: "This collection is used as an example to help you develop your next Flow NFT.",
96                        externalURL: MetadataViews.ExternalURL("https://example-nft.onflow.org"),
97                        squareImage: media,
98                        bannerImage: media,
99                        socials: {
100                            "twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain")
101                        }
102                    )
103                case Type<MetadataViews.Traits>():
104                    // exclude mintedTime and foo to show other uses of Traits
105                    let excludedTraits = ["mintedTime", "foo"]
106                    let traitsView = MetadataViews.dictToTraits(dict: self.metadata, excludedNames: excludedTraits)
107
108                    // mintedTime is a unix timestamp, we should mark it with a displayType so platforms know how to show it.
109                    let mintedTimeTrait = MetadataViews.Trait(name: "mintedTime", value: self.metadata["mintedTime"]!, displayType: "Date", rarity: nil)
110                    traitsView.addTrait(mintedTimeTrait)
111
112                    // foo is a trait with its own rarity
113                    let fooTraitRarity = MetadataViews.Rarity(score: 10.0, max: 100.0, description: "Common")
114                    let fooTrait = MetadataViews.Trait(name: "foo", value: self.metadata["foo"], displayType: nil, rarity: fooTraitRarity)
115                    traitsView.addTrait(fooTrait)
116                    
117                    return traitsView
118
119            }
120            return nil
121        }
122    }
123
124    pub resource interface CollectionPublic {
125        pub fun deposit(token: @NonFungibleToken.NFT)
126        pub fun getIDs(): [UInt64]
127        pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT
128        pub fun borrowChainzKey(id: UInt64): &ChainzKey.NFT? {
129            post {
130                (result == nil) || (result?.id == id):
131                    "Cannot borrow ChainzKey reference: the ID of the returned reference is incorrect"
132            }
133        }
134    }
135
136    pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic, MetadataViews.ResolverCollection {
137        // dictionary of NFT conforming tokens
138        // NFT is a resource type with an `UInt64` ID field
139        pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT}
140
141        init () {
142            self.ownedNFTs <- {}
143        }
144
145        // withdraw removes an NFT from the collection and moves it to the caller
146        pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT {
147            let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
148
149            emit Withdraw(id: token.id, from: self.owner?.address)
150
151            return <-token
152        }
153
154        // deposit takes a NFT and adds it to the collections dictionary
155        // and adds the ID to the id array
156        pub fun deposit(token: @NonFungibleToken.NFT) {
157            let token <- token as! @ChainzKey.NFT
158            let id: UInt64 = token.id
159            // add the new token to the dictionary which removes the old one
160            self.ownedNFTs[id] <-! token
161            emit Deposit(id: id, to: self.owner?.address)
162        }
163
164        // getIDs returns an array of the IDs that are in the collection
165        pub fun getIDs(): [UInt64] {
166            return self.ownedNFTs.keys
167        }
168
169        // borrowNFT gets a reference to an NFT in the collection
170        // so that the caller can read its metadata and call its methods
171        pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT {
172            return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)!
173        }
174 
175        pub fun borrowChainzKey(id: UInt64): &ChainzKey.NFT? {
176            if self.ownedNFTs[id] != nil {
177                // Create an authorized reference to allow downcasting
178                let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
179                return ref as! &ChainzKey.NFT
180            }
181
182            return nil
183        }
184
185        pub fun borrowViewResolver(id: UInt64): &AnyResource{MetadataViews.Resolver} {
186            let nft = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
187            let ChainzKey = nft as! &ChainzKey.NFT
188            return ChainzKey as &AnyResource{MetadataViews.Resolver}
189        }
190
191        destroy() {
192            destroy self.ownedNFTs
193        }
194    }
195
196    // public function that anyone can call to create a new empty collection
197    pub fun createEmptyCollection(): @NonFungibleToken.Collection {
198        return <- create Collection()
199    }
200
201    access(account) fun createNFT(tier: String, type: String, serial: UInt64, metadata: {String: String}): @NFT {
202        return <- create NFT(tier: tier, type: type, serial: serial, metadata: metadata)
203    }
204
205    init() {
206        // Initialize the total supply
207        self.totalSupply = 0
208
209        // Set the named paths
210        self.CollectionStoragePath = /storage/ChainzKeyCollection
211        self.CollectionPublicPath = /public/ChainzKeyCollection
212        self.MinterStoragePath = /storage/ChainzKeyMinter
213
214        emit ContractInitialized()
215    }
216}
217