Smart Contract
BBxBarbieCard
A.e5bf4d436ca23932.BBxBarbieCard
1/*
2*
3* An NFT contract for redeeming/minting unlimited tokens
4*
5*
6*/
7
8import NonFungibleToken from 0x1d7e57aa55817448
9import FungibleToken from 0xf233dcee88fe0abe
10import MetadataViews from 0x1d7e57aa55817448
11import ViewResolver from 0x1d7e57aa55817448
12
13access(all) contract BBxBarbieCard: NonFungibleToken {
14
15 /*
16 * NonFungibleToken Standard Events
17 */
18 access(all) event ContractInitialized()
19 access(all) event Withdraw(id: UInt64, from: Address?)
20 access(all) event Deposit(id: UInt64, to: Address?)
21
22 /*
23 * Project Events
24 */
25 access(all) event Mint(id: UInt64)
26 access(all) event Burn(id: UInt64)
27 access(all) event DepositEvent(
28 uuid: UInt64
29 , id: UInt64
30 , seriesId: UInt64
31 , editionId: UInt64
32 , to: Address?
33 )
34
35 access(all) event TransferEvent(
36 uuid: UInt64
37 , id: UInt64
38 , seriesId: UInt64
39 , editionId: UInt64
40 , to: Address?
41 )
42
43 /*
44 * Named Paths
45 */
46 access(all) let CollectionStoragePath: StoragePath
47 access(all) let CollectionPublicPath: PublicPath
48
49 /*
50 * NonFungibleToken Standard Fields
51 */
52 access(all) var totalSupply: UInt64
53
54 /*
55 * Card State Variables
56 */
57 access(self) var name: String
58 access(account) var currentCardEditionIdByPackSeriesId: {UInt64: UInt64}
59
60 access(all) resource NFT: NonFungibleToken.NFT {
61 access(all) let id: UInt64 // aka cardEditionID
62
63 access(all) let packSeriesID: UInt64
64 access(all) let cardEditionID: UInt64
65 access(all) let packHash: String
66 access(all) let redeemable: String
67 access(all) let metadata: {String: String}
68
69 access(all) view fun getViews(): [Type] {
70 return [
71 Type<MetadataViews.Display>(),
72 Type<MetadataViews.ExternalURL>(),
73 Type<MetadataViews.NFTCollectionData>(),
74 Type<MetadataViews.NFTCollectionDisplay>(),
75 Type<MetadataViews.Royalties>(),
76 Type<MetadataViews.Traits>(),
77 Type<MetadataViews.Editions>(),
78 Type<MetadataViews.Serial>(),
79 Type<MetadataViews.Medias>(),
80 Type<MetadataViews.Rarity>()
81 ]
82 }
83
84 access(all) fun resolveView(_ view: Type): AnyStruct? {
85 switch view {
86 case Type<MetadataViews.Display>():
87 var ipfsImage = MetadataViews.IPFSFile(
88 cid: self.metadata["thumbnailCID"] ?? "ThumnailCID not set"
89 , path: self.metadata["thumbnailPath"] ?? "ThumbnailPath not set"
90 )
91 return MetadataViews.Display(
92 name: self.metadata["name"]?.concat(" Card #")?.concat(self.cardEditionID.toString()) ?? "Boss Beauties x Barbie Card",
93 description: self.metadata["description"] ?? "Digital Card Collectable from the Boss Beauties x Barbie collaboration" ,
94 thumbnail: ipfsImage
95 )
96
97 case Type<MetadataViews.ExternalURL>():
98 return MetadataViews.ExternalURL(
99 self.metadata["url"] ?? ""
100 )
101
102 case Type<MetadataViews.NFTCollectionData>():
103 return BBxBarbieCard.resolveContractView(resourceType: Type<@BBxBarbieCard.NFT>(), viewType: Type<MetadataViews.NFTCollectionData>())
104
105 case Type<MetadataViews.NFTCollectionDisplay>():
106 return BBxBarbieCard.resolveContractView(resourceType: Type<@BBxBarbieCard.NFT>(), viewType: Type<MetadataViews.NFTCollectionDisplay>())
107 case Type<MetadataViews.Royalties>():
108 return BBxBarbieCard.resolveContractView(resourceType: Type<@BBxBarbieCard.NFT>(), viewType: Type<MetadataViews.Royalties>())
109 case Type<MetadataViews.Traits>():
110 let excludedTraits = [
111 "thumbnailPath"
112 , "thumbnailCID"
113 , "career"
114 , "careerDescription"
115 , "description"
116 , "url"
117 ]
118 let traitsView = MetadataViews.dictToTraits(
119 dict: self.metadata
120 , excludedNames: excludedTraits
121 )
122
123 return traitsView
124 case Type<MetadataViews.Editions>():
125 return MetadataViews.Edition(
126 name: nil
127 , number: self.id
128 , max: nil
129 )
130 case Type<MetadataViews.Serial>():
131 return MetadataViews.Serial(
132 self.uuid
133 )
134 case Type<MetadataViews.Medias>():
135 return [
136 ]
137 case Type<MetadataViews.Rarity>():
138 return MetadataViews.Rarity(
139 score: nil
140 , max: nil
141 , description: self.metadata["rarity"]
142 )
143 }
144 return nil
145 }
146
147 init(
148 id: UInt64
149 , packSeriesID: UInt64
150 , cardEditionID: UInt64
151 , packHash: String
152 , redeemable: String
153 , metadata: {String: String}
154 ) {
155 self.id = id
156 self.packSeriesID = packSeriesID
157 self.cardEditionID = cardEditionID
158 self.packHash = packHash
159 self.redeemable = redeemable
160 self.metadata = metadata
161 emit Mint(id: self.id)
162 }
163
164 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
165 return <-BBxBarbieCard.createEmptyCollection(nftType: Type<@BBxBarbieCard.NFT>())
166 }
167 }
168
169 access(all) resource interface CardCollectionPublic {}
170
171 access(all) resource Collection: CardCollectionPublic, NonFungibleToken.Collection {
172 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
173
174 init() {
175 self.ownedNFTs <- {}
176 }
177
178 /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
179 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
180 let supportedTypes: {Type: Bool} = {}
181 supportedTypes[Type<@BBxBarbieCard.NFT>()] = true
182 return supportedTypes
183 }
184
185 /// Returns whether or not the given type is accepted by the collection
186 /// A collection that can accept any type should just return true by default
187 access(all) view fun isSupportedNFTType(type: Type): Bool {
188 return type == Type<@BBxBarbieCard.NFT>()
189 }
190
191 access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
192 let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
193
194 emit Withdraw(id: token.id, from: self.owner?.address)
195
196 return <-token
197 }
198
199 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
200 let BBxBarbieCard <- token as! @BBxBarbieCard.NFT
201 let BBxBarbieCardUUID: UInt64 = BBxBarbieCard.uuid
202 let BBxBarbieCardSeriesId: UInt64 = BBxBarbieCard.packSeriesID
203 let BBxBarbieCardID: UInt64 = BBxBarbieCard.id
204 let BBxBarbieCardEditionID: UInt64 = BBxBarbieCard.cardEditionID
205
206 self.ownedNFTs[BBxBarbieCardID] <-! BBxBarbieCard
207
208 emit Deposit(
209 id: BBxBarbieCardID
210 , to: self.owner?.address
211 )
212 emit DepositEvent(
213 uuid:BBxBarbieCardUUID
214 , id: BBxBarbieCardID
215 , seriesId: BBxBarbieCardSeriesId
216 , editionId: BBxBarbieCardEditionID
217 , to: self.owner?.address
218 )
219 }
220
221 access(all) view fun getIDs(): [UInt64] {
222 return self.ownedNFTs.keys
223 }
224
225 access(all) view fun getLength(): Int {
226 return self.ownedNFTs.keys.length
227 }
228
229 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
230 return (&self.ownedNFTs[id])
231 }
232
233 access(all) view fun borrowCard(id: UInt64): &NFT? {
234 if let cardRef: &{NonFungibleToken.NFT} = &self.ownedNFTs[id] {
235 return cardRef as! &NFT
236 } else {
237 return nil
238 }
239 }
240
241 access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
242 if let nftRef: &{NonFungibleToken.NFT} = &self.ownedNFTs[id] {
243 return nftRef as &{ViewResolver.Resolver}
244 }
245 return nil
246 }
247
248 /// Allows a given function to iterate through the list
249 /// of owned NFT IDs in a collection without first
250 /// having to load the entire list into memory
251 access(all) fun forEachID(_ f: fun(UInt64): Bool) {
252 self.ownedNFTs.forEachKey(f)
253 }
254
255 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
256 return <- BBxBarbieCard.createEmptyCollection(nftType: Type<@BBxBarbieCard.NFT>())
257 }
258 }
259
260
261 /*
262 * Public Functions
263 */
264
265 access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
266 return <- create Collection()
267 }
268
269 access(all) fun getTotalSupply(): UInt64 {
270 return self.totalSupply
271 }
272
273 access(all) fun getName(): String {
274 return self.name
275 }
276
277 access(all) fun transfer(uuid: UInt64, id: UInt64, packSeriesId: UInt64, cardEditionId: UInt64, toAddress: Address){
278
279 let BBxBarbieCardV2UUID: UInt64 = uuid
280 let BBxBarbieCardV2SeriesId: UInt64 = packSeriesId
281 let BBxBarbieCardV2ID: UInt64 = id
282 let BBxBarbieCardV2cardEditionID: UInt64 = cardEditionId
283
284 emit TransferEvent(
285 uuid: BBxBarbieCardV2UUID
286 , id: BBxBarbieCardV2ID
287 , seriesId: BBxBarbieCardV2SeriesId
288 , editionId: BBxBarbieCardV2cardEditionID
289 , to: toAddress)
290 }
291
292
293 access(all) view fun getContractViews(resourceType: Type?): [Type] {
294 return [
295 Type<MetadataViews.NFTCollectionData>(),
296 Type<MetadataViews.NFTCollectionDisplay>(),
297 Type<MetadataViews.Royalties>()
298 ]
299 }
300
301 access(all) view fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
302 switch viewType {
303 case Type<MetadataViews.NFTCollectionData>():
304 return MetadataViews.NFTCollectionData(
305 storagePath: BBxBarbieCard.CollectionStoragePath,
306 publicPath: BBxBarbieCard.CollectionPublicPath,
307 publicCollection: Type<&BBxBarbieCard.Collection>(),
308 publicLinkedType: Type<&BBxBarbieCard.Collection>(),
309 createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} {
310 return <- BBxBarbieCard.createEmptyCollection(nftType: Type<@BBxBarbieCard.NFT>())})
311 )
312 case Type<MetadataViews.NFTCollectionDisplay>():
313 let externalURL = MetadataViews.ExternalURL(
314 "https://mattel.com/"
315 )
316 let squareImage = MetadataViews.Media(
317 file: MetadataViews.HTTPFile(
318 url: "https://www.mattel.com/"
319 ),
320 mediaType: "image/png")
321 let bannerImage = MetadataViews.Media(
322 file: MetadataViews.HTTPFile(
323 url: "https://www.mattel.com/"
324 ),
325 mediaType: "image/png")
326 let socialMap: {String: MetadataViews.ExternalURL} = {
327 "facebook": MetadataViews.ExternalURL(
328 "https://www.facebook.com/mattel"
329 ),
330 "instagram": MetadataViews.ExternalURL(
331 "https://www.instagram.com/mattel"
332 ),
333 "twitter": MetadataViews.ExternalURL(
334 "https://www.twitter.com/mattel"
335 )
336 }
337 return MetadataViews.NFTCollectionDisplay(
338 name: "Boss Beauties x Barbie Card",
339 description: "Digital Collectable from the Boss Beauties x Barbie collaboration",
340 externalURL: externalURL,
341 squareImage: squareImage,
342 bannerImage: bannerImage,
343 socials: socialMap
344 )
345 case Type<MetadataViews.Royalties>():
346 let flowReciever = getAccount(0xf86e2f015cd692be).capabilities.get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)
347 return MetadataViews.Royalties([
348 MetadataViews.Royalty(
349 receiver:flowReciever
350 , cut: 0.05
351 , description: "Mattel 5% Royalty")
352 ]
353 )
354 }
355 return nil
356 }
357
358 /*
359 * Admin Functions
360 */
361 access(account) fun addNewSeries(newCardSeriesID: UInt64){
362 self.currentCardEditionIdByPackSeriesId.insert(key: newCardSeriesID, 0)
363 }
364
365
366 access(account) fun updateCurrentEditionIdByPackSeriesId(packSeriesID: UInt64, cardSeriesEdition: UInt64){
367 self.currentCardEditionIdByPackSeriesId[packSeriesID] = cardSeriesEdition
368 }
369
370
371 access(account) fun mint(
372 nftID: UInt64
373 , packSeriesID: UInt64
374 , cardEditionID: UInt64
375 , packHash: String
376 , metadata: {String: String}
377 ): @{NonFungibleToken.NFT} {
378
379 self.totalSupply = self.getTotalSupply() + 1
380
381 self.currentCardEditionIdByPackSeriesId[packSeriesID] = self.currentCardEditionIdByPackSeriesId[packSeriesID]! + 1
382
383 return <- create NFT(
384 id: nftID
385 , packSeriesID: packSeriesID
386 , cardEditionID: self.currentCardEditionIdByPackSeriesId[packSeriesID]!
387 , packHash: packHash
388 , redeemable: metadata["redeemable"]!
389 , metadata: metadata
390 )
391 }
392
393 // initialize contract state variables
394 init(){
395 self.name = "Boss Beauties x Barbie Card"
396 self.totalSupply = 0
397 self.currentCardEditionIdByPackSeriesId = {1 : 0}
398
399 // set the named paths
400 self.CollectionStoragePath = /storage/BBxBarbieCardCollection
401 self.CollectionPublicPath = /public/BBxBarbieCardCollection
402
403 // create a collection resource and save it to storage
404 let collection: @BBxBarbieCard.Collection <- create Collection()
405 self.account.storage.save(<-collection, to: self.CollectionStoragePath)
406
407 let collectionCap = self.account.capabilities.storage.issue<&BBxBarbieCard.Collection>(self.CollectionStoragePath)
408 self.account.capabilities.publish(collectionCap, at: self.CollectionPublicPath)
409
410 emit ContractInitialized()
411 }
412
413
414}
415