Smart Contract
NFL
A.8f3e345219de6fed.NFL
1// Description: Smart Contract for NFL Virtual Commemorative Tickets
2// SPDX-License-Identifier: UNLICENSED
3
4import NonFungibleToken from 0x1d7e57aa55817448
5import MetadataViews from 0x1d7e57aa55817448
6import ViewResolver from 0x1d7e57aa55817448
7
8access(all) contract NFL : NonFungibleToken {
9
10 access(all) var totalSupply: UInt64
11
12 access(all) event ContractInitialized()
13 access(all) event Withdraw(id: UInt64, from: Address?)
14 access(all) event Deposit(id: UInt64, to: Address?)
15
16 access(all) let CollectionStoragePath: StoragePath
17 access(all) let CollectionPublicPath: PublicPath
18 access(all) let MinterStoragePath: StoragePath
19
20 // Correct type from NonFungibleToken.INFT to NonFungibleToken.NFT and MetadataViews.Resolver
21 access(all) resource NFT : NonFungibleToken.NFT {
22 access(all) let id: UInt64
23 access(all) var link: String
24 access(all) var batch: UInt32
25 access(all) var sequence: UInt16
26 access(all) var limit: UInt16
27
28 init(
29 initID: UInt64,
30 initlink: String,
31 initbatch: UInt32,
32 initsequence: UInt16,
33 initlimit: UInt16
34 ) {
35 self.id = initID
36 self.link = initlink
37 self.batch = initbatch
38 self.sequence = initsequence
39 self.limit = initlimit
40 }
41
42 /// createEmptyCollection creates an empty Collection
43 /// and returns it to the caller so that they can own NFTs
44 /// @{NonFungibleToken.Collection}
45 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
46 return <-NFL.createEmptyCollection(nftType: Type<@NFL.NFT>())
47 }
48
49 access(all) view fun getViews(): [Type] {
50 return [
51 Type<MetadataViews.NFTCollectionData>()
52 ]
53 }
54
55 access(all) fun resolveView(_ view: Type): AnyStruct? {
56 switch view {
57 case Type<MetadataViews.NFTCollectionData>():
58 return NFL.resolveContractView(resourceType: Type<@NFL.NFT>(), viewType: Type<MetadataViews.NFTCollectionData>())
59 }
60 return nil
61 }
62 }
63
64 // Ensure all type specifications conform to interface requirements
65 access(all) resource interface NFLCollectionPublic {
66 // Depracated, only here for backwards compatibility
67 }
68
69 access(all) resource Collection : NonFungibleToken.Collection, NFLCollectionPublic {
70 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
71
72 init() {
73 self.ownedNFTs <- {}
74 }
75
76 /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
77 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
78 let supportedTypes: {Type: Bool} = {}
79 supportedTypes[Type<@NFL.NFT>()] = true
80 return supportedTypes
81 }
82
83 /// Returns whether or not the given type is accepted by the collection
84 /// A collection that can accept any type should just return true by default
85 access(all) view fun isSupportedNFTType(type: Type): Bool {
86 return type == Type<@NFL.NFT>()
87 }
88
89
90 /// withdraw removes an NFT from the collection and moves it to the caller
91 access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
92 let token <- self.ownedNFTs.remove(key: withdrawID)
93 ?? panic("Could not withdraw an NFT with the provided ID from the collection")
94
95 return <-token
96 }
97
98 /// deposit takes a NFT and adds it to the collections dictionary
99 /// and adds the ID to the id array
100 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
101 let token <- token as! @NFL.NFT
102 let id = token.id
103
104 // add the new token to the dictionary which removes the old one
105 let oldToken <- self.ownedNFTs[token.id] <- token
106
107 destroy oldToken
108
109 // This code is for testing purposes only
110 // Do not add to your contract unless you have a specific
111 // reason to want to emit the NFTUpdated event somewhere
112 // in your contract
113 let authTokenRef = (&self.ownedNFTs[id] as auth(NonFungibleToken.Update) &{NonFungibleToken.NFT}?)!
114 //authTokenRef.updateTransferDate(date: getCurrentBlock().timestamp)
115 NFL.emitNFTUpdated(authTokenRef)
116 }
117 /// getIDs returns an array of the IDs that are in the collection
118 access(all) view fun getIDs(): [UInt64] {
119 return self.ownedNFTs.keys
120 }
121
122 /// Gets the amount of NFTs stored in the collection
123 access(all) view fun getLength(): Int {
124 return self.ownedNFTs.length
125 }
126
127
128 /// Borrow the view resolver for the specified NFT ID
129 access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
130 if let nft = &self.ownedNFTs[id] as &{NonFungibleToken.NFT}? {
131 return nft as &{ViewResolver.Resolver}
132 }
133 return nil
134 }
135
136
137 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
138 return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)
139 }
140
141 /// createEmptyCollection creates an empty Collection of the same type
142 /// and returns it to the caller
143 /// @return A an empty collection of the same type
144 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
145 return <- NFL.createEmptyCollection(nftType: Type<@NFL.NFT>())
146 }
147
148 }
149
150 /// createEmptyCollection creates an empty Collection for the specified NFT type
151 /// and returns it to the caller so that they can own NFTs
152 access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
153 return <- create Collection()
154 }
155
156 /// Function that returns all the Metadata Views implemented by a Non Fungible Token
157 ///
158 /// @return An array of Types defining the implemented views. This value will be used by
159 /// developers to know which parameter to pass to the resolveView() method.
160 ///
161 access(all) view fun getContractViews(resourceType: Type?): [Type] {
162 return [
163 Type<MetadataViews.NFTCollectionData>(),
164 Type<MetadataViews.NFTCollectionDisplay>(),
165 Type<MetadataViews.EVMBridgedMetadata>()
166 ]
167 }
168
169 /// Function that resolves a metadata view for this contract.
170 ///
171 /// @param view: The Type of the desired view.
172 /// @return A structure representing the requested view.
173 ///
174 access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
175 switch viewType {
176 case Type<MetadataViews.NFTCollectionData>():
177 let collectionData = MetadataViews.NFTCollectionData(
178 storagePath: self.CollectionStoragePath,
179 publicPath: self.CollectionPublicPath,
180 publicCollection: Type<&NFL.Collection>(),
181 publicLinkedType: Type<&NFL.Collection>(),
182 createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} {
183 return <-NFL.createEmptyCollection(nftType: Type<@NFL.NFT>())
184 })
185 )
186 return collectionData
187 case Type<MetadataViews.NFTCollectionDisplay>():
188 let media = MetadataViews.Media(
189 file: MetadataViews.HTTPFile(
190 url: "https://assets.website-files.com/5f6294c0c7a8cdd643b1c820/5f6294c0c7a8cda55cb1c936_Flow_Wordmark.svg"
191 ),
192 mediaType: "image/svg+xml"
193 )
194 return MetadataViews.NFTCollectionDisplay(
195 name: "The Example Collection",
196 description: "This collection is used as an example to help you develop your next Flow NFT.",
197 externalURL: MetadataViews.ExternalURL("https://example-nft.onflow.org"),
198 squareImage: media,
199 bannerImage: media,
200 socials: {
201 "twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain")
202 }
203 )
204 case Type<MetadataViews.EVMBridgedMetadata>():
205 // Implementing this view gives the project control over how the bridged NFT is represented as an ERC721
206 // when bridged to EVM on Flow via the public infrastructure bridge.
207
208 // Compose the contract-level URI. In this case, the contract metadata is located on some HTTP host,
209 // but it could be IPFS, S3, a data URL containing the JSON directly, etc.
210 return MetadataViews.EVMBridgedMetadata(
211 name: "NFL",
212 symbol: "XMPL",
213 uri: MetadataViews.URI(
214 baseURI: nil, // setting baseURI as nil sets the given value as the uri field value
215 value: "https://nfl-nft.onflow.org/contract-metadata.json"
216 )
217 )
218 }
219 return nil
220 }
221
222
223 /// Resource that an admin or something similar would own to be
224 /// able to mint new NFTs
225 ///
226 access(all) resource NFTMinter {
227
228 /// mintNFT mints a new NFT with a new ID
229 /// and returns it to the calling context
230 access(all) fun mintNFT(
231 glink: String,
232 gbatch: UInt32,
233 glimit: UInt16,
234 gsequence: UInt16
235 ): @NFL.NFT {
236
237 let tokenID = (UInt64(gbatch) << 32) | (UInt64(glimit) << 16) | UInt64(gsequence)
238
239 let metadata: {String: AnyStruct} = {}
240 let currentBlock = getCurrentBlock()
241 metadata["mintedBlock"] = currentBlock.height
242 metadata["mintedTime"] = currentBlock.timestamp
243
244 // this piece of metadata will be used to show embedding rarity into a trait
245 metadata["foo"] = "bar"
246
247 // create a new NFT
248 var newNFT <- create NFT(
249 initID: tokenID,
250 initlink: glink,
251 initbatch: gbatch,
252 initsequence: gsequence,
253 initlimit: glimit
254 )
255 NFL.totalSupply = NFL.totalSupply + 1
256 return <-newNFT
257 }
258 }
259
260 init() {
261 self.CollectionStoragePath = /storage/NFLCollection
262 self.CollectionPublicPath = /public/NFLCollection
263 self.MinterStoragePath = /storage/NFLMinter
264 self.totalSupply = 0
265
266 let collection <- create Collection()
267 self.account.storage.save(<-collection, to: self.CollectionStoragePath)
268
269 let collectionCap = self.account.capabilities.storage.issue<&NFL.Collection>(self.CollectionStoragePath)
270 self.account.capabilities.publish(collectionCap, at: self.CollectionPublicPath)
271
272 let minter <- create NFTMinter()
273 self.account.storage.save(<-minter, to: self.MinterStoragePath)
274 }
275}
276