Smart Contract
BBxBarbieToken
A.e5bf4d436ca23932.BBxBarbieToken
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 BBxBarbieToken: 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 * Token State Variables
56 */
57 access(self) var name: String
58 access(account) var currentTokenEditionIdByPackSeriesId: {UInt64: UInt64}
59
60 access(all) resource NFT: NonFungibleToken.NFT {
61 access(all) let id: UInt64
62 access(all) let packSeriesID: UInt64
63 access(all) let tokenEditionID: UInt64
64 access(all) let redeemable: String
65 access(all) let metadata: {String: String}
66
67 access(all) view fun getViews(): [Type] {
68 return [
69 Type<MetadataViews.Display>(),
70 Type<MetadataViews.ExternalURL>(),
71 Type<MetadataViews.NFTCollectionData>(),
72 Type<MetadataViews.NFTCollectionDisplay>(),
73 Type<MetadataViews.Royalties>(),
74 Type<MetadataViews.Traits>()
75 ]
76 }
77
78 access(all) fun resolveView(_ view: Type): AnyStruct? {
79 switch view {
80 case Type<MetadataViews.Display>():
81 var ipfsImage = MetadataViews.IPFSFile(
82 cid: self.metadata["thumbnailCID"] ?? "ThumnailCID not set"
83 , path: self.metadata["thumbnailPath"] ?? "ThumbnailPath not set"
84 )
85 return MetadataViews.Display(
86 name: self.metadata["name"]?.concat(" Token #")?.concat(self.tokenEditionID.toString()) ?? "Boss Beauties x Barbie Redeemable Token",
87 description: self.metadata["description"] ?? "Digital Redeemable Token Collectable from the Boss Beauties x Barbie collaboration" ,
88 thumbnail: ipfsImage
89 )
90
91 case Type<MetadataViews.ExternalURL>():
92 return MetadataViews.ExternalURL(
93 self.metadata["url"] ?? ""
94 )
95
96 case Type<MetadataViews.NFTCollectionData>():
97 return BBxBarbieToken.resolveContractView(resourceType: Type<@BBxBarbieToken.NFT>(), viewType: Type<MetadataViews.NFTCollectionData>())
98
99
100 case Type<MetadataViews.NFTCollectionDisplay>():
101 return BBxBarbieToken.resolveContractView(resourceType: Type<@BBxBarbieToken.NFT>(), viewType: Type<MetadataViews.NFTCollectionDisplay>())
102
103 case Type<MetadataViews.Traits>():
104 let excludedTraits = [
105 "thumbnailPath"
106 , "thumbnailCID"
107 , "drop"
108 , "dropDescription"
109 , "description"
110 , "url"
111 ]
112 let traitsView = MetadataViews.dictToTraits(
113 dict: self.metadata
114 , excludedNames: excludedTraits
115 )
116
117 return traitsView
118 case Type<MetadataViews.Royalties>():
119 return BBxBarbieToken.resolveContractView(resourceType: Type<@BBxBarbieToken.NFT>(), viewType: Type<MetadataViews.Royalties>())
120 }
121 return nil
122 }
123
124 init(
125 id: UInt64
126 , packSeriesID: UInt64
127 , tokenEditionID: UInt64
128 , redeemable: String
129 , metadata: {String: String}
130 ) {
131 self.id = id
132 self.packSeriesID = packSeriesID
133 self.tokenEditionID = tokenEditionID
134 self.redeemable = redeemable
135 self.metadata = metadata
136 emit Mint(id: self.id)
137 }
138
139 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
140 return <-BBxBarbieToken.createEmptyCollection(nftType: Type<@BBxBarbieToken.NFT>())
141 }
142 }
143
144 access(all) resource interface TokenCollectionPublic {}
145
146 access(all) resource Collection: TokenCollectionPublic, NonFungibleToken.Collection {
147 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
148
149 init() {
150 self.ownedNFTs <- {}
151 }
152
153
154 /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
155 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
156 let supportedTypes: {Type: Bool} = {}
157 supportedTypes[Type<@BBxBarbieToken.NFT>()] = true
158 return supportedTypes
159 }
160
161 /// Returns whether or not the given type is accepted by the collection
162 /// A collection that can accept any type should just return true by default
163 access(all) view fun isSupportedNFTType(type: Type): Bool {
164 return type == Type<@BBxBarbieToken.NFT>()
165 }
166
167 access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
168 let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
169
170 emit Withdraw(id: token.id, from: self.owner?.address)
171
172 return <-token
173 }
174
175
176 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
177 let BBxBarbieToken <- token as! @BBxBarbieToken.NFT
178 let BBxBarbieTokenUUID: UInt64 = BBxBarbieToken.uuid
179 let BBxBarbieTokenSeriesId: UInt64 = BBxBarbieToken.packSeriesID
180 let BBxBarbieTokenID: UInt64 = BBxBarbieToken.id
181 let BBxBarbieTokenEditionID: UInt64 = BBxBarbieToken.tokenEditionID
182 self.ownedNFTs[BBxBarbieTokenID] <-! BBxBarbieToken
183
184 emit Deposit(
185 id: BBxBarbieTokenID
186 , to: self.owner?.address
187 )
188 emit DepositEvent(
189 uuid:BBxBarbieTokenUUID
190 , id: BBxBarbieTokenID
191 , seriesId: BBxBarbieTokenSeriesId
192 , editionId: BBxBarbieTokenEditionID
193 , to: self.owner?.address
194 )
195
196 }
197
198 access(all) view fun getIDs(): [UInt64] {
199 return self.ownedNFTs.keys
200 }
201
202 access(all) view fun getLength(): Int {
203 return self.ownedNFTs.keys.length
204 }
205
206 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}?{
207 return (&self.ownedNFTs[id])
208 }
209
210 access(all) view fun borrowToken(id: UInt64): &NFT? {
211 if let tokenRef: &{NonFungibleToken.NFT} = &self.ownedNFTs[id] {
212 return tokenRef as! &NFT
213 } else {
214 return nil
215 }
216 }
217
218 access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
219 if let nftRef: &{NonFungibleToken.NFT} = &self.ownedNFTs[id] {
220 return nftRef as &{ViewResolver.Resolver}
221 }
222 return nil
223 }
224
225 /// Allows a given function to iterate through the list
226 /// of owned NFT IDs in a collection without first
227 /// having to load the entire list into memory
228 access(all) fun forEachID(_ f: fun(UInt64): Bool) {
229 self.ownedNFTs.forEachKey(f)
230 }
231
232
233 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
234 return <- BBxBarbieToken.createEmptyCollection(nftType: Type<@BBxBarbieToken.NFT>())
235 }
236 }
237
238 /*
239 * Public Functions
240 */
241
242 access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
243 return <- create Collection()
244 }
245
246 access(all) view fun getTotalSupply(): UInt64 {
247 return self.totalSupply
248 }
249
250
251 access(all) view fun getName(): String {
252 return self.name
253 }
254
255 access(all) fun transfer(uuid: UInt64, id: UInt64, packSeriesId: UInt64, tokenEditionId: UInt64, toAddress: Address){
256
257 let BBxBarbieTokenV2UUID: UInt64 = uuid
258 let BBxBarbieTokenV2SeriesId: UInt64 = packSeriesId
259 let BBxBarbieTokenV2ID: UInt64 = id
260 let BBxBarbieTokenV2tokenEditionID: UInt64 = tokenEditionId
261
262 emit TransferEvent(
263 uuid: BBxBarbieTokenV2UUID
264 , id: BBxBarbieTokenV2ID
265 , seriesId: BBxBarbieTokenV2SeriesId
266 , editionId: BBxBarbieTokenV2tokenEditionID
267 , to: toAddress)
268 }
269
270 access(all) view fun getContractViews(resourceType: Type?): [Type] {
271 return [
272 Type<MetadataViews.NFTCollectionData>(),
273 Type<MetadataViews.NFTCollectionDisplay>(),
274 Type<MetadataViews.Royalties>()
275 ]
276 }
277
278
279
280 access(all) view fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
281 switch viewType {
282 case Type<MetadataViews.NFTCollectionData>():
283 return MetadataViews.NFTCollectionData(
284 storagePath: BBxBarbieToken.CollectionStoragePath,
285 publicPath: BBxBarbieToken.CollectionPublicPath,
286 publicCollection: Type<&BBxBarbieToken.Collection>(),
287 publicLinkedType: Type<&BBxBarbieToken.Collection>(),
288 createEmptyCollectionFunction: fun(): @{NonFungibleToken.Collection} {return <- BBxBarbieToken.createEmptyCollection(nftType: Type<@BBxBarbieToken.NFT>())
289 })
290
291 case Type<MetadataViews.NFTCollectionDisplay>():
292 let externalURL = MetadataViews.ExternalURL(
293 "https://mattel.com/"
294 )
295 let squareImage = MetadataViews.Media(
296 file: MetadataViews.HTTPFile(
297 url: "https://www.mattel.com/"
298 ),
299 mediaType: "image/png")
300 let bannerImage = MetadataViews.Media(
301 file: MetadataViews.HTTPFile(
302 url: "https://www.mattel.com/"
303 ),
304 mediaType: "image/png")
305 let socialMap: {String: MetadataViews.ExternalURL} = {
306 "facebook": MetadataViews.ExternalURL(
307 "https://www.facebook.com/mattel"
308 ),
309 "instagram": MetadataViews.ExternalURL(
310 "https://www.instagram.com/mattel"
311 ),
312 "twitter": MetadataViews.ExternalURL(
313 "https://www.twitter.com/mattel"
314 )
315 }
316 return MetadataViews.NFTCollectionDisplay(
317 name: "Boss Beauties x Barbie Token",
318 description: "Digital Collectable from the Boss Beauties x Barbie collaboration",
319 externalURL: externalURL,
320 squareImage: squareImage,
321 bannerImage: bannerImage,
322 socials: socialMap
323 )
324 case Type<MetadataViews.Royalties>():
325 let flowReciever = getAccount(0xf86e2f015cd692be).capabilities.get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)
326 return MetadataViews.Royalties([
327 MetadataViews.Royalty(
328 receiver:flowReciever
329 , cut: 0.05
330 , description: "Mattel 5% Royalty")
331 ]
332 )
333 }
334 return nil
335 }
336
337
338
339 /*
340 * Admin Functions
341 */
342 access(account) fun addNewSeries(newTokenSeriesID: UInt64){
343 self.currentTokenEditionIdByPackSeriesId.insert(key: newTokenSeriesID, 0)
344 }
345
346
347 access(account) fun updateCurrentEditionIdByPackSeriesId(packSeriesID: UInt64, tokenSeriesEdition: UInt64){
348 self.currentTokenEditionIdByPackSeriesId[packSeriesID] = tokenSeriesEdition
349 }
350
351 access(account) fun mint(
352 nftID: UInt64
353 , packSeriesID: UInt64
354 , tokenEditionID: UInt64
355 , metadata: {String: String}
356 ): @{NonFungibleToken.NFT} {
357
358 self.totalSupply = self.getTotalSupply() + 1
359
360 self.currentTokenEditionIdByPackSeriesId[packSeriesID] = self.currentTokenEditionIdByPackSeriesId[packSeriesID]! + 1
361
362 return <- create NFT(
363 id: nftID
364 , packSeriesID: packSeriesID
365 , tokenEditionID: self.currentTokenEditionIdByPackSeriesId[packSeriesID]!
366 , redeemable: metadata["redeemable"]!
367 , metadata: metadata
368 )
369 }
370
371 // initialize contract state variables
372 init(){
373 self.name = "Boss Beauties x Barbie Token"
374 self.totalSupply = 0
375 self.currentTokenEditionIdByPackSeriesId = {1 : 0}
376
377 // set the named paths
378 self.CollectionStoragePath = /storage/BBxBarbieTokenCollection
379 self.CollectionPublicPath = /public/BBxBarbieTokenCollection
380
381 // create a collection resource and save it to storage
382 let collection: @BBxBarbieToken.Collection <- create Collection()
383 self.account.storage.save(<-collection, to: self.CollectionStoragePath)
384
385 let collectionCap = self.account.capabilities.storage.issue<&BBxBarbieToken.Collection>(self.CollectionStoragePath)
386 self.account.capabilities.publish(collectionCap, at: self.CollectionPublicPath)
387
388 emit ContractInitialized()
389 }
390
391}
392