Smart Contract

HWGarageCard

A.d0bcefdf1e67ea85.HWGarageCard

Deployed

1w ago
Feb 15, 2026, 01:08:27 PM UTC

Dependents

93 imports
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}