Smart Contract
HWGarageCard
A.d0bcefdf1e67ea85.HWGarageCard
1/*
2*
3* An NFT contract demo for redeeming/minting unlimited tokens
4*
5*
6*/
7
8import NonFungibleToken from 0x1d7e57aa55817448
9import MetadataViews from 0x1d7e57aa55817448
10import ViewResolver from 0x1d7e57aa55817448
11import FungibleToken from 0xf233dcee88fe0abe
12
13access(all) contract HWGarageCard: NonFungibleToken {
14
15 /*
16 * NonFungibleToken Standard Events
17 */
18
19 access(all) event ContractInitialized()
20 access(all) event Withdraw(id: UInt64, from: Address?)
21 access(all) event Deposit(id: UInt64, to: Address?)
22
23 /*
24 * Project Events
25 */
26
27 access(all) event Mint(id: UInt64)
28 access(all) event Burn(id: UInt64)
29 access(all) event DepositEvent(
30 uuid: UInt64,
31 id: UInt64,
32 seriesId: UInt64,
33 editionId: UInt64,
34 to: Address?
35 )
36 access(all) event TransferEvent(
37 uuid: UInt64,
38 id: UInt64,
39 seriesId: UInt64,
40 editionId: UInt64,
41 to: Address?
42 )
43
44 /*
45 * Named Paths
46 */
47
48 access(all) let CollectionStoragePath: StoragePath
49 access(all) let CollectionPublicPath: PublicPath
50
51 /*
52 * NonFungibleToken Standard Fields
53 */
54
55 access(all) var totalSupply: UInt64
56
57 /*
58 * Token State Variables
59 */
60
61 access(all) var name: String
62
63 access(self) var collectionMetadata: { String: String }
64 access(self) let idToTokenMetadata: { UInt64: TokenMetadata }
65
66 access(all) struct TokenMetadata {
67 access(all) let metadata: { String: String }
68
69 init(metadata: { String: String }) {
70 self.metadata = metadata
71 }
72 }
73
74 access(all) resource NFT: NonFungibleToken.NFT {
75 access(all) let id: UInt64
76 access(all) let packID: UInt64
77
78 access(all) view fun getMetadata(): {String: String} {
79 if (HWGarageCard.idToTokenMetadata[self.id] != nil){
80 return HWGarageCard.idToTokenMetadata[self.id]!.metadata
81 } else {
82 return {}
83 }
84 }
85
86 init(id: UInt64, packID: UInt64) {
87 self.id = id
88 self.packID = packID
89 emit Mint(id: self.id)
90 }
91
92 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
93 return <-HWGarageCard.createEmptyCollection(nftType: Type<@HWGarageCard.NFT>())
94 }
95
96 access(all) view fun getViews(): [Type] {
97 return [
98 Type<MetadataViews.Display>(),
99 Type<MetadataViews.ExternalURL>(),
100 Type<MetadataViews.NFTCollectionData>(),
101 Type<MetadataViews.NFTCollectionDisplay>(),
102 Type<MetadataViews.Royalties>()
103 ]
104 }
105
106 access(all) view fun resolveView(_ view: Type): AnyStruct? {
107 switch view {
108 case Type<MetadataViews.Display>():
109 var ipfsImage: MetadataViews.IPFSFile = MetadataViews.IPFSFile(cid: "No thumbnail cid set", path: "No thumbnail path set")
110 if (self.getMetadata().containsKey("thumbnailCID")){
111 ipfsImage = MetadataViews.IPFSFile(cid: self.getMetadata()["thumbnailCID"]!, path: self.getMetadata()["thumbnailPath"])
112 }
113 return MetadataViews.Display(
114 name: self.getMetadata()["name"] ?? "Hot Wheels Garage Card Series 4 #".concat(self.id.toString()),
115 description: self.getMetadata()["description"] ?? "Digital Card Collectable from Hot Wheels Garage",
116 thumbnail: ipfsImage
117 )
118
119
120
121 case Type<MetadataViews.ExternalURL>():
122 return MetadataViews.ExternalURL("")
123
124
125 case Type<MetadataViews.NFTCollectionData>():
126 return HWGarageCard.resolveContractView(resourceType: Type<@HWGarageCard.NFT>(), viewType: Type<MetadataViews.NFTCollectionData>())
127
128 case Type<MetadataViews.NFTCollectionDisplay>():
129 return HWGarageCard.resolveContractView(resourceType: Type<@HWGarageCard.NFT>(),viewType: Type<MetadataViews.NFTCollectionDisplay>())
130
131 case Type<MetadataViews.Royalties>():
132 return HWGarageCard.resolveContractView(resourceType: Type<@HWGarageCard.NFT>(), viewType: Type<MetadataViews.Royalties>())
133 }
134
135 return nil
136 }
137
138 }
139
140 access(all) resource interface HWGarageCardCollectionPublic {}
141
142 access(all) resource Collection: HWGarageCardCollectionPublic, NonFungibleToken.Collection {
143 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
144
145 init() {
146 self.ownedNFTs <- {}
147 }
148
149 /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
150 access(all) view fun getSupportedNFTTypes(): {Type: Bool}{
151 let supportedTypes: {Type: Bool} = {}
152 supportedTypes[Type<@HWGarageCard.NFT>()] = true
153 return supportedTypes
154 }
155
156 /// Returns whether or not the given type is accepted by the collection
157 /// A collection that can accept any type should just return true by default
158 access(all) view fun isSupportedNFTType(type: Type): Bool {
159 return type == Type<@HWGarageCard.NFT>()
160 }
161
162 access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
163 let token: @{NonFungibleToken.NFT} <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
164 emit Withdraw(id: token.id, from: self.owner?.address)
165 return <-token
166 }
167
168 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
169 // let token <- token as! @HWGarageCard.NFT
170 // let id: UInt64 = token.id
171 let HWGarageCard: @HWGarageCard.NFT <- token as! @HWGarageCard.NFT
172 let HWGarageCardUUID: UInt64 = HWGarageCard.uuid
173 let HWGarageCardSeriesId: UInt64 = 4
174 let HWGarageCardID: UInt64 = HWGarageCard.id
175 let HWGarageCardcardEditionID: UInt64 = HWGarageCard.id
176 self.ownedNFTs[HWGarageCardID] <-! HWGarageCard
177 emit Deposit(id: HWGarageCardID, to: self.owner?.address)
178 emit DepositEvent(
179 uuid: HWGarageCardUUID,
180 id: HWGarageCardID,
181 seriesId: HWGarageCardSeriesId,
182 editionId: HWGarageCardcardEditionID,
183 to: self.owner?.address
184 )
185 }
186
187 access(all) view fun getIDs(): [UInt64] {
188 return self.ownedNFTs.keys
189 }
190
191 access(all) view fun getLength(): Int {
192 return self.ownedNFTs.keys.length
193 }
194 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
195 return (&self.ownedNFTs[id])
196 }
197
198 access(all) view fun borrowHWGarageCard(id: UInt64): &NFT? {
199 if let card: &{NonFungibleToken.NFT} = &self.ownedNFTs[id] {
200 return card as! &NFT
201 }
202 return nil
203 }
204
205 access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
206 if let nftRef: &{NonFungibleToken.NFT} = (&self.ownedNFTs[id]) {
207 return nftRef as &{ViewResolver.Resolver}
208 }
209 return nil
210 }
211
212 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
213 return <- HWGarageCard.createEmptyCollection(nftType: Type<@HWGarageCard.NFT>())
214 }
215 }
216
217 access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
218 return <- create Collection()
219 }
220
221 access(all) view fun getContractViews(resourceType: Type?): [Type] {
222 return [
223 Type<MetadataViews.NFTCollectionData>(),
224 Type<MetadataViews.NFTCollectionDisplay>(),
225 Type<MetadataViews.Royalties>()
226 ]
227 }
228
229 access(all) view fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
230 switch viewType {
231 case Type<MetadataViews.NFTCollectionData>():
232 return MetadataViews.NFTCollectionData(
233 storagePath: self.CollectionStoragePath,
234 publicPath: self.CollectionPublicPath,
235 publicCollection: Type<&HWGarageCard.Collection>(),
236 publicLinkedType: Type<&HWGarageCard.Collection>(),
237 createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} {
238 return <-HWGarageCard.createEmptyCollection(nftType: Type<@HWGarageCard.NFT>())
239 })
240 )
241
242 case Type<MetadataViews.NFTCollectionDisplay>():
243 let externalURL = MetadataViews.ExternalURL("")
244 let squareImage = MetadataViews.Media(
245 file: MetadataViews.HTTPFile(url: ""),
246 mediaType: "image/png"
247 )
248 let bannerImage = MetadataViews.Media(
249 file: MetadataViews.HTTPFile(url: ""),
250 mediaType: "image/png"
251 )
252 let socialMap: {String: MetadataViews.ExternalURL} = {
253 "facebook": MetadataViews.ExternalURL("https://www.facebook.com/hotwheels"),
254 "instagram": MetadataViews.ExternalURL("https://www.instagram.com/hotwheelsofficial/"),
255 "twitter": MetadataViews.ExternalURL("https://twitter.com/Hot_Wheels"),
256 "discord": MetadataViews.ExternalURL("https://discord.gg/mattel")
257 }
258 return MetadataViews.NFTCollectionDisplay(
259 name: "Hot Wheels Garage Card",
260 description: "Digital Collectable from Hot Wheels Garage",
261 externalURL: externalURL,
262 squareImage: squareImage,
263 bannerImage: bannerImage,
264 socials: socialMap
265 )
266 case Type<MetadataViews.Royalties>():
267 let flowReceiver = getAccount(0xf86e2f015cd692be).capabilities.get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)
268 return MetadataViews.Royalties([
269 MetadataViews.Royalty(
270 receiver: flowReceiver,
271 cut: 0.05,
272 description: "Mattel 5% Royalty"
273 )
274 ])
275 }
276 return nil
277 }
278
279 /*
280 * Admin Functions
281 */
282 access(account) fun setEditionMetadata(editionNumber: UInt64, metadata: {String: String}) {
283 self.idToTokenMetadata[editionNumber] = TokenMetadata(metadata: metadata)
284 }
285
286 access(account) fun setCollectionMetadata(metadata: {String: String}) {
287 self.collectionMetadata = metadata
288 }
289
290 access(account) fun mint(nftID: UInt64, packID: UInt64): @NFT {
291 self.totalSupply = self.totalSupply + 1
292 return <- create NFT(id: nftID, packID: packID)
293 }
294
295 /*
296 * Public Functions
297 */
298 access(all) view fun getTotalSupply(): UInt64 {
299 return self.totalSupply
300 }
301
302 access(all) view fun getName(): String {
303 return self.name
304 }
305
306 access(all) fun transfer(uuid: UInt64, id: UInt64, packSeriesId: UInt64, cardEditionId: UInt64, toAddress: Address){
307
308 let HWGarageCardV2UUID: UInt64 = uuid
309 let HWGarageCardV2SeriesId: UInt64 = packSeriesId
310 let HWGarageCardV2ID: UInt64 = id
311 let HWGarageCardV2cardEditionID: UInt64 = cardEditionId
312
313 emit TransferEvent(
314 uuid: HWGarageCardV2UUID
315 , id: HWGarageCardV2ID
316 , seriesId: HWGarageCardV2SeriesId
317 , editionId: HWGarageCardV2cardEditionID
318 , to: toAddress)
319 }
320
321 access(all) view fun getCollectionMetadata(): {String: String} {
322 return self.collectionMetadata
323 }
324
325 access(all) view fun getEditionMetadata(_ edition: UInt64): {String: String} {
326 if ( self.idToTokenMetadata[edition] != nil) {
327 return self.idToTokenMetadata[edition]!.metadata
328 } else {
329 return {}
330 }
331 }
332
333 access(all) view fun getMetadataLength(): Int {
334 return self.idToTokenMetadata.length
335 }
336
337 // initialize contract state variables
338 init(){
339 self.name = "HWGarageCard"
340 self.totalSupply = 0
341
342 self.collectionMetadata = {}
343 self.idToTokenMetadata = {}
344
345 // set the named paths
346 self.CollectionStoragePath = /storage/HWGarageCardCollection
347 self.CollectionPublicPath = /public/HWGarageCardCollection
348
349 // Create a collection resource and save it to storage
350 let collection: @HWGarageCard.Collection <- create Collection()
351 self.account.storage.save(<-collection, to: self.CollectionStoragePath)
352
353 let collectionCap = self.account.capabilities.storage.issue<&HWGarageCard.Collection>(self.CollectionStoragePath)
354 self.account.capabilities.publish(collectionCap, at: self.CollectionPublicPath)
355
356
357 emit ContractInitialized()
358 }
359}