Smart Contract
ChainzKey
A.ff342b6df9ef019d.ChainzKey
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