Smart Contract
GooberXContract
A.34f2bf4a80bb0f69.GooberXContract
1/**
2* SPDX-License-Identifier: GPL-3.0-only
3*/
4
5import FungibleToken from 0xf233dcee88fe0abe
6import ViewResolver from 0x1d7e57aa55817448
7import FlowToken from 0x1654653399040a61
8import NonFungibleToken from 0x1d7e57aa55817448
9import MetadataViews from 0x1d7e57aa55817448
10import FindUtils from 0x097bafa4e0b48eef
11import Profile from 0x097bafa4e0b48eef
12
13// GooberXContract - The contract Erik needs to party !
14access(all)
15contract GooberXContract: NonFungibleToken{
16
17 access(all) entitlement Owner
18 // Data
19 //
20 // Array of goober IDs in creation order for paged access
21 access(self)
22 var gooberRegister: [UInt64]
23
24 // Contains all minted goobers including the payload
25 access(self)
26 var mintedGoobers: [GooberStruct]
27
28 // Index containing the reference between GooberID and the GooberStruct
29 access(self)
30 var mintedGoobersIndex:{ UInt64: Int}
31
32 // Pool of mintable goobers
33 access(self)
34 var gooberPool: [GooberStruct]
35
36 // Giveaways
37 access(self)
38 var giveaways:{ String: GooberStruct}
39
40 // Events
41 //
42 // Event to be emitted when the contract is initialized
43 access(all)
44 event ContractInitialized()
45
46 // Event to be emitted whenever a NFT is withdrawn from a collection
47 access(all)
48 event Withdraw(id: UInt64, from: Address?)
49
50 // Event to be emitted whenever a NFT is deposited to a collection
51 access(all)
52 event Deposit(id: UInt64, to: Address?)
53
54 // Event to be eitted whenever a new NFT is minted
55 access(all)
56 event Minted(id: UInt64, uri: String, price: UFix64)
57
58 // Event to be emitted whenever a new NFT is minted
59 access(all)
60 event Airdropped(id: UInt64)
61
62 // Event to be emitted whenever a Goober is named differently
63 access(all)
64 event NamedGoober(id: UInt64, name: String)
65
66 // Collection Paths
67 //
68 // Private collection storage path
69 access(all)
70 let CollectionStoragePath: StoragePath
71
72 // Public collection storage path
73 access(all)
74 let CollectionPublicPath: PublicPath
75
76 // Admin storage path
77 access(all)
78 let AdminStoragePath: StoragePath
79
80 // totalSupply
81 access(all)
82 var totalSupply: UInt64
83
84 // Index pointing to the first Goober in the pool
85 access(all)
86 var firstGooberInPoolIndex: UInt64
87
88 // Goober data structure
89 // This structure is used to store the payload of the Goober NFT
90 //
91 access(all)
92 struct GooberStruct{
93 access(all)
94 let gooberID: UInt64
95
96 // Metadata of the Goober
97 access(all)
98 let metadata:{ String: AnyStruct}
99
100 // URI pointing to the IPFS address of the picture related to the Goober NFT
101 access(all)
102 let uri: String
103
104 // Price of the Goober NFT
105 access(all)
106 let price: UFix64
107
108 // init
109 // Constructor method to initialize a Goober
110 //
111 init(gooberID: UInt64, uri: String, metadata:{ String: AnyStruct}, price: UFix64){
112 self.gooberID = gooberID
113 self.uri = uri
114 self.metadata = metadata
115 self.price = price
116 }
117
118 access(Owner)
119 fun setName(name: String){
120 self.metadata.insert(key: "name", name)
121 }
122 }
123
124 // Goober NFT
125 access(all)
126 resource NFT: NonFungibleToken.NFT, ViewResolver.Resolver{
127
128 // NFT id
129 access(all)
130 let id: UInt64
131
132 // Data structure containing all relevant describing data
133 access(account)
134 let data: GooberStruct
135
136
137 access(account)
138 fun getData() : GooberStruct {
139 return self.data
140 }
141 // init
142 // Constructor to initialize the Goober NFT
143 // Requires a GooberStruct to be passed
144 //
145 init(goober: GooberStruct){
146 GooberXContract.totalSupply = GooberXContract.totalSupply + 1
147 let gooberID = GooberXContract.totalSupply
148 self.data = GooberStruct(gooberID: gooberID, uri: goober.uri, metadata: goober.metadata, price: goober.price)
149 self.id = UInt64(self.data.gooberID)
150 GooberXContract.gooberRegister.append(self.data.gooberID)
151 GooberXContract.mintedGoobers.append(self.data)
152 GooberXContract.mintedGoobersIndex[self.data.gooberID] = GooberXContract.mintedGoobers.length - 1
153 }
154
155 access(all)
156 view fun getViews(): [Type]{
157 return [Type<MetadataViews.Display>(), Type<MetadataViews.ExternalURL>(), Type<MetadataViews.Royalties>(), Type<MetadataViews.NFTCollectionData>(), Type<MetadataViews.NFTCollectionDisplay>(), Type<MetadataViews.Traits>()]
158 }
159
160 access(all)
161 fun resolveView(_ view: Type): AnyStruct?{
162 switch view{
163 case Type<MetadataViews.Display>():
164 var name = "Party Goob #".concat(self.id.toString())
165 if let nameValue = self.data.metadata["name"]{
166 if let n = nameValue! as? String{
167 name = n!
168 }
169 }
170 return MetadataViews.Display(name: name, description: "Party Goob #".concat(self.id.toString()), thumbnail: MetadataViews.IPFSFile(cid: self.data.uri.slice(from: "ipfs://".length, upTo: self.data.uri.length), path: nil))
171 case Type<MetadataViews.ExternalURL>():
172 return MetadataViews.ExternalURL("https://partymansion.io/gooberz/".concat(self.id.toString()))
173 case Type<MetadataViews.Royalties>():
174 let cap = Profile.findReceiverCapability(address: GooberXContract.account.address, path: /public/flowTokenReceiver, type: Type<@FlowToken.Vault>())!
175 return MetadataViews.Royalties([MetadataViews.Royalty(receiver: cap, cut: 0.06, description: "Party Mansion")])
176 case Type<MetadataViews.NFTCollectionData>():
177 return MetadataViews.NFTCollectionData(storagePath: GooberXContract.CollectionStoragePath, publicPath: GooberXContract.CollectionPublicPath, publicCollection: Type<&GooberXContract.Collection>(), publicLinkedType: Type<&GooberXContract.Collection>(), createEmptyCollectionFunction: fun (): @{NonFungibleToken.Collection}{
178 return <-GooberXContract.createEmptyCollection(nftType: Type<@GooberXContract.Collection>())
179 })
180 case Type<MetadataViews.NFTCollectionDisplay>():
181 return MetadataViews.NFTCollectionDisplay(name: "Party Mansion Gooberz", description: "The Party Gooberz is a fun and comical art collection of 3550 collectibles living on the Flow Blockchain. As one of the first PFP collectibles on Flow, we enjoy bringing the party and hanging with friends. So grab a drink, pump up the music, and get ready to party because The Party Goobz are ready to go within Party Mansion!", externalURL: MetadataViews.ExternalURL("https://partymansion.io/"), squareImage: MetadataViews.Media(file: MetadataViews.IPFSFile(cid: "QmeiwpEXCidsPae3ZPpSJTKVit1R2LHiF4cw5pvmMPRC4x", path: nil), mediaType: "image/jpg"), bannerImage: MetadataViews.Media(file: MetadataViews.IPFSFile(cid: "QmdU1j5nqeQBmVWZZDhz23z6mMPwMp5i2Ka2sBpMhYggPT", path: nil), mediaType: "image/jpg"), socials:{ "twitter": MetadataViews.ExternalURL("https://mobile.twitter.com/the_goobz_nft"), "discord": MetadataViews.ExternalURL("http://discord.gg/zJRNqKuDQH")})
182 case Type<MetadataViews.Traits>():
183 let traits: [MetadataViews.Trait] = []
184 for traitName in self.data.metadata.keys{
185 if FindUtils.hasSuffix(traitName, suffix: "Cnt"){
186 continue
187 }
188 let traitValue = self.data.metadata[traitName]
189 let max = self.data.metadata[traitName.concat("Cnt")]
190 if traitValue != nil{
191 if let t = traitValue! as? String{
192 if max != nil{
193 if let m = max! as? UInt32{
194 // The data here does not account for gooberz that are burned right now.
195 // The partymansion.io currently shows the latests data after burn
196
197 // Add a burn registry and fetch all the burnt data / traits.
198 traits.append(MetadataViews.Trait(name: FindUtils.to_snake_case(traitName), value: t, displayType: "String", rarity: MetadataViews.Rarity(score: UFix64(m!), max: 5975.0, description: "The rarity here is including burned Gooberz")))
199 continue
200 }
201 }
202 traits.append(MetadataViews.Trait(name: FindUtils.to_snake_case(traitName), value: t, displayType: "String", rarity: nil))
203 continue
204 }
205 }
206 }
207 return MetadataViews.Traits(traits)
208 }
209 return nil
210 }
211
212 access(all)
213 fun createEmptyCollection(): @{NonFungibleToken.Collection}{
214 return <-create Collection()
215 }
216 }
217
218 // Interface to publicly acccess GooberCollections
219 access(all)
220 resource interface GooberCollectionPublic{
221
222 // Deposit NFT
223 // Param token refers to a NonFungibleToken.NFT to be deposited within this collection
224 //
225 access(all)
226 fun deposit(token: @{NonFungibleToken.NFT}): Void
227
228 // Get all IDs related to the current Goober Collection
229 // returns an Array of IDs
230 //
231 access(all)
232 view fun getIDs(): [UInt64]
233
234 // Borrow NonFungibleToken NFT with ID from current Goober Collection
235 // Param id refers to a Goober ID
236 // Returns a reference to the NonFungibleToken.NFT
237 //
238 access(all)
239 view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}?
240
241 // Eventually borrow Goober NFT with ID from current Goober Collection
242 // Returns an option reference to GooberXContract.NFT
243 //
244 access(all)
245 fun borrowGoober(id: UInt64): &GooberXContract.NFT?{
246 // If the result isn't nil, the id of the returned reference
247 // should be the same as the argument to the function
248 post{
249 result == nil || result?.id == id:
250 "Cannot borrow Goober reference: The ID of the returned reference is incorrect"
251 }
252 }
253
254 // List all goobers the user of the current collection owns
255 // Returns a dictionary having the id as key and a GooberStruct as value
256 //
257 access(all)
258 fun listUsersGoobers():{ UInt64: GooberStruct}
259
260 // List a paged resultset of Goobers of the users collection
261 // Param page determines the current page of the resultset
262 // Param pageSize determines the maximum size of the resultset
263 // Returns a dictionary having the id as key and a GooberStruct as value
264 //
265 access(all)
266 fun listUsersGoobersPaged(page: UInt32, pageSize: UInt32):{ UInt64: GooberStruct}
267 }
268
269 // Resource to define methods to be used by an Admin in order to administer and populate
270 // the Goobers
271 //
272 access(all)
273 resource Admin{
274
275 // Pre-mints Goobers in a global pool
276 // Populates a pool. Each time a user mints a goober from the pool
277 // the first Goober is removed from the pool and minted as a NFT
278 // in the users collection.
279 //
280 access(Owner)
281 fun addGooberToPool(uri: String, metadata:{ String: AnyStruct}, address: Address, price: UFix64){
282 pre{
283 uri.length > 0:
284 "Could not create Goober: uri is required."
285 }
286 GooberXContract.gooberPool.append(GooberStruct(gooberID: 0 as UInt64, uri: uri, metadata: metadata, price: price))
287 }
288
289 // Replaces Goobers in global pool
290 // This is used to exchange existing Goober Pool
291 //
292 access(Owner)
293 fun replaceGooberInPool(uri: String, metadata:{ String: AnyStruct}, address: Address, price: UFix64, index: Int){
294 pre{
295 uri.length > 0:
296 "Could not create Goober: uri is required."
297 index >= 0:
298 "Index is out of bounds"
299 GooberXContract.gooberPool.length > index:
300 "Index is out of bounds."
301 }
302 GooberXContract.gooberPool[index] = GooberStruct(gooberID: 0 as UInt64, uri: uri, metadata: metadata, price: price)
303 }
304
305 // removeGooberFromPool
306 // removes a goober from the pool using a index paramter
307 //
308 access(Owner)
309 fun removeGooberFromPool(index: UInt64){
310 pre{
311 GooberXContract.gooberPool[index] != nil:
312 "Could not delete goober from pool: goober does not exist."
313 }
314 GooberXContract.gooberPool.remove(at: index)
315 }
316
317 // adminMintNFT
318 // Mints a new NFT with a new ID
319 // to the contract owner account for free
320 //
321 access(Owner)
322 fun adminMintNFT(recipient: &{NonFungibleToken.CollectionPublic}){
323 pre{
324 GooberXContract.gooberPool.length > 0:
325 "GooberPool doesnt contain any goober to mint"
326 }
327
328 // deposit it in the recipient's account using their reference
329 let gooberFromPool: GooberStruct = GooberXContract.gooberPool.remove(at: GooberXContract.firstGooberInPoolIndex)
330 recipient.deposit(token: <-create GooberXContract.NFT(goober: gooberFromPool!))
331 emit Minted(id: GooberXContract.totalSupply, uri: (gooberFromPool!).uri, price: (gooberFromPool!).price)
332 }
333
334 // adminMintAirDropNFT
335 // Mints a new NFT with a new ID and airdrops the Goober to a Recipient
336 //
337 access(Owner)
338 fun adminMintAirDropNFT(uri: String, metadata:{ String: AnyStruct}, address: Address, price: UFix64, recipient: &{NonFungibleToken.CollectionPublic}){
339 pre{
340 uri.length > 0:
341 "Could not create Goober: uri is required."
342 }
343 // GooberStruct initializing
344 let goober: GooberStruct = GooberStruct(gooberID: 0 as UInt64, uri: uri, metadata: metadata, price: price)
345 recipient.deposit(token: <-create GooberXContract.NFT(goober: goober))
346 emit Minted(id: GooberXContract.totalSupply, uri: (goober!).uri, price: (goober!).price)
347 emit Airdropped(id: GooberXContract.totalSupply)
348 }
349
350 // createGiveaway
351 // add a new Giveaway key to the available giveaways
352 // Important: the code needs to be hashed sha3_256 off chain
353 //
354 access(Owner)
355 fun createGiveaway(giveawayKey: String){
356 pre{
357 GooberXContract.gooberPool.length > 0:
358 "GooberPool doesnt contain any goober to add as giveaway"
359 }
360 if GooberXContract.giveaways.containsKey(giveawayKey){
361 panic("Giveaway code already known.")
362 }
363 let gooberFromPool: GooberStruct = GooberXContract.gooberPool.remove(at: GooberXContract.firstGooberInPoolIndex)
364 GooberXContract.giveaways.insert(key: giveawayKey, gooberFromPool)
365 }
366 }
367
368 // Collection
369 // A collection of Goober NFTs owned by an account
370 //
371 access(all)
372 resource Collection: GooberCollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.Collection, NonFungibleToken.CollectionPublic, ViewResolver.ResolverCollection{
373 // dictionary of NFT conforming tokens
374 // NFT is a resource type with an `UInt64` ID field
375 //
376 access(all)
377 var ownedNFTs: @{UInt64:{ NonFungibleToken.NFT}}
378
379 // withdraw
380 // Removes an NFT from the collection and moves it to the caller
381 //
382 access(NonFungibleToken.Withdraw)
383 fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT}{
384 let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
385 return <-token
386 }
387
388 // deposit
389 // Takes a NFT and adds it to the collections dictionary
390 // and adds the ID to the id array
391 //
392 access(all)
393 fun deposit(token: @{NonFungibleToken.NFT}): Void{
394 let token <- token as! @GooberXContract.NFT
395 let id: UInt64 = token.id
396
397 // add the new token to the dictionary which removes the old one
398 let oldToken <- self.ownedNFTs[id] <- token
399 // destroy old resource
400 destroy oldToken
401
402 // update goober overview
403 let index = GooberXContract.mintedGoobersIndex[id]
404 let tmpGoober: GooberStruct = GooberXContract.mintedGoobers[index!]
405 GooberXContract.mintedGoobers[index!] = GooberStruct(gooberID: tmpGoober.gooberID, uri: tmpGoober.uri, metadata: tmpGoober.metadata, price: tmpGoober.price)
406 }
407
408 // getIDs
409 // Returns an array of the IDs that are in the collection
410 //
411 access(all)
412 view fun getIDs(): [UInt64]{
413 return self.ownedNFTs.keys
414 }
415
416 // borrowNFT
417 // Gets a reference to an NFT in the collection
418 // so that the caller can read its metadata and call its methods
419 //
420 access(all)
421 view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}?{
422 return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
423 }
424
425 // borrowGoober
426 // Gets a reference to an NFT in the collection as a Goober,
427 // exposing all data.
428 // This is safe as there are no functions that can be called on the Goober.
429 //
430 access(all)
431 fun borrowGoober(id: UInt64): &GooberXContract.NFT?{
432 if self.ownedNFTs[id] != nil{
433 let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
434 return ref as! &GooberXContract.NFT
435 } else{
436 return nil
437 }
438 }
439
440 access(all)
441 view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}?{
442 if self.ownedNFTs[id] != nil{
443 let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
444 return ref as! &GooberXContract.NFT
445 }
446 panic("Missing NFT. ID : ".concat(id.toString()))
447 }
448
449 // List all goobers the user of the current collection owns
450 // Returns a dictionary having the id as key and a GooberStruct as value
451 //
452 access(all)
453 fun listUsersGoobers():{ UInt64: GooberStruct}{
454 var goobers:{ UInt64: GooberStruct} ={}
455 for key in self.ownedNFTs.keys{
456 let el = (&self.ownedNFTs[key] as &{NonFungibleToken.NFT}?)!
457 let goober = el as! &GooberXContract.NFT
458 goobers.insert(key: goober.id, goober.getData())
459 }
460 return goobers
461 }
462
463 // List a paged resultset of Goobers of the users collection
464 // Param page determines the current page of the resultset
465 // Param pageSize determines the maximum size of the resultset
466 // Returns a dictionary having the id as key and a GooberStruct as value
467 //
468 access(all)
469 fun listUsersGoobersPaged(page: UInt32, pageSize: UInt32):{ UInt64: GooberStruct}{
470 var it: UInt32 = 0
471 var goobers:{ UInt64: GooberStruct} ={}
472 let len: Int = self.ownedNFTs.length
473 let beginIndex: UInt32 = page * pageSize
474 let endIndex: UInt32 = page * pageSize + pageSize
475
476 // Optimize method to return empty dictionary when the paging is beyond borders
477 if beginIndex + 1 > UInt32(len){
478 return goobers
479 }
480
481 // Iterate all keys because regular index, contains not possible
482 for key in self.ownedNFTs.keys{
483 if it >= beginIndex && it < endIndex{
484 let el = (&self.ownedNFTs[key] as &{NonFungibleToken.NFT}?)!
485 let goober = el as! &GooberXContract.NFT
486 goobers.insert(key: goober.id, goober.getData())
487 }
488 // Increment iterator
489 it = it + 1
490 // Check boundary
491 if it > endIndex{
492 break
493 }
494 }
495 return goobers
496 }
497 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
498 return { Type<@NFT>() : true}
499 }
500
501 access(all) view fun isSupportedNFTType(type: Type) : Bool {
502 return type == Type<@NFT>()
503 }
504
505 access(all)
506 fun createEmptyCollection(): @{NonFungibleToken.Collection}{
507 return <-create Collection()
508 }
509
510 // destructor
511 //
512 // initializer
513 //
514 init(){
515 self.ownedNFTs <-{}
516 }
517 }
518
519 access(all) view fun getContractViews(resourceType: Type?): [Type] {
520 return [
521 Type<MetadataViews.NFTCollectionData>(),
522 Type<MetadataViews.NFTCollectionDisplay>()
523 ]
524 }
525
526 access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
527 switch viewType {
528 case Type<MetadataViews.NFTCollectionData>():
529 return MetadataViews.NFTCollectionData(storagePath: GooberXContract.CollectionStoragePath, publicPath: GooberXContract.CollectionPublicPath, publicCollection: Type<&GooberXContract.Collection>(), publicLinkedType: Type<&GooberXContract.Collection>(), createEmptyCollectionFunction: fun (): @{NonFungibleToken.Collection}{
530 return <-GooberXContract.createEmptyCollection(nftType: Type<@GooberXContract.Collection>())
531 })
532 case Type<MetadataViews.NFTCollectionDisplay>():
533 return MetadataViews.NFTCollectionDisplay(name: "Party Mansion Gooberz", description: "The Party Gooberz is a fun and comical art collection of 3550 collectibles living on the Flow Blockchain. As one of the first PFP collectibles on Flow, we enjoy bringing the party and hanging with friends. So grab a drink, pump up the music, and get ready to party because The Party Goobz are ready to go within Party Mansion!", externalURL: MetadataViews.ExternalURL("https://partymansion.io/"), squareImage: MetadataViews.Media(file: MetadataViews.IPFSFile(cid: "QmeiwpEXCidsPae3ZPpSJTKVit1R2LHiF4cw5pvmMPRC4x", path: nil), mediaType: "image/jpg"), bannerImage: MetadataViews.Media(file: MetadataViews.IPFSFile(cid: "QmdU1j5nqeQBmVWZZDhz23z6mMPwMp5i2Ka2sBpMhYggPT", path: nil), mediaType: "image/jpg"), socials:{ "twitter": MetadataViews.ExternalURL("https://mobile.twitter.com/the_goobz_nft"), "discord": MetadataViews.ExternalURL("http://discord.gg/zJRNqKuDQH")})
534
535 }
536 return nil
537 }
538
539 // createEmptyCollection
540 // public function that anyone can call to create a new empty collection
541 //
542 access(all)
543 fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection}{
544 return <-create Collection()
545 }
546
547 /*
548 // mintNFT
549 // Mints a new NFT with a new ID
550 // and deposit it in the recipients collection using their collection reference
551 //
552 access(Owner)
553 fun mintNFT(recipient: &{NonFungibleToken.CollectionPublic}, address: Address, paymentVault: @{FungibleToken.Vault}){
554 pre{
555 GooberXContract.gooberPool.length > 0:
556 "GooberPool doesnt contain any goober to mint"
557 paymentVault.balance >= GooberXContract.gooberPool[GooberXContract.firstGooberInPoolIndex].price:
558 "Could not mint goober: payment balance insufficient."
559 paymentVault.isInstance(Type<@FUSD.Vault>()):
560 "payment vault is not requested fungible token"
561 }
562
563 // pay
564 let gooberContractAccount: &Account = getAccount(GooberXContract.account.address)
565 let gooberContractReceiver: Capability<&{FungibleToken.Receiver}> = gooberContractAccount.capabilities.get<&FUSD.Vault>(/public/fusdReceiver)!
566 let borrowGooberContractReceiver = gooberContractReceiver.borrow()!
567 borrowGooberContractReceiver.deposit(from: <-paymentVault.withdraw(amount: paymentVault.balance))
568
569 // deposit it in the recipient's account using their reference
570 let gooberFromPool: GooberStruct = GooberXContract.gooberPool.remove(at: GooberXContract.firstGooberInPoolIndex)
571 recipient.deposit(token: <-create GooberXContract.NFT(goober: gooberFromPool!))
572 emit Minted(id: GooberXContract.totalSupply, uri: (gooberFromPool!).uri, price: (gooberFromPool!).price)
573 destroy paymentVault
574 }
575
576 // retrieveGiveaway
577 // Retrieves a giveaway and adds a new NFT with a new ID
578 // and deposit it in the recipients collection using their collection reference
579 //
580 access(Owner)
581 fun retrieveGiveaway(recipient: &{NonFungibleToken.CollectionPublic}, address: Address, giveawayCode: String){
582 // Hash giveawayCode
583 let digest = HashAlgorithm.SHA3_256.hash(giveawayCode.decodeHex())
584 let giveawayKey = String.encodeHex(digest)
585 if !GooberXContract.giveaways.containsKey(giveawayKey){
586 let msg = "Unknown Giveaway Code:"
587 panic(msg.concat(giveawayKey))
588 }
589
590 // deposit it in the recipient's account using their reference
591 let goober = GooberXContract.giveaways[giveawayKey]
592 recipient.deposit(token: <-create GooberXContract.NFT(goober: goober!))
593 GooberXContract.giveaways.remove(key: giveawayKey)
594 emit Minted(id: GooberXContract.totalSupply, uri: (goober!).uri, price: (goober!).price)
595 }
596
597 // nameYourGoober
598 // Give your Goober a name
599 access(Owner)
600 fun nameYourGoober(newName: String, gooberID: UInt64, collection: &GooberXContract.Collection, paymentVault: @{FungibleToken.Vault}){
601 pre{
602 paymentVault.balance >= UFix64(5):
603 "Could not mint goober: payment balance insufficient."
604 paymentVault.isInstance(Type<@FUSD.Vault>()):
605 "payment vault is not requested fungible token"
606 newName.length <= 20:
607 "Cannot give the Goober a name which is longer than 20 characters"
608 }
609
610 // pay
611 let gooberContractAccount: &Account = getAccount(GooberXContract.account.address)
612 let gooberContractReceiver: Capability<&{FungibleToken.Receiver}> = gooberContractAccount.capabilities.get<&FUSD.Vault>(/public/fusdReceiver)!
613 let borrowGooberContractReceiver = gooberContractReceiver.borrow()!
614 borrowGooberContractReceiver.deposit(from: <-paymentVault.withdraw(amount: paymentVault.balance))
615
616 // name Goober
617 let token <- collection.withdraw(withdrawID: gooberID) as! @GooberXContract.NFT
618 token.data.setName(name: newName)
619
620 // update Goober information in contract
621 self.mintedGoobers[self.mintedGoobersIndex[token.data.gooberID]!] = token.data
622
623 // Deposit updated NFT
624 collection.deposit(token: <-token)
625
626 // emit Naming Event
627 emit NamedGoober(id: gooberID, name: newName)
628 destroy paymentVault
629 }
630 */
631
632 // getGoober
633 // fetches a goober from the minted goobers index
634 // Param gooberID refers to a Goober ID
635 // returns the GooberStruct refered by the Goober ID
636 //
637 access(all)
638 fun getGoober(gooberID: UInt64): GooberStruct{
639 let index: Int = self.mintedGoobersIndex[gooberID]!
640 let goober = self.mintedGoobers[index]
641 return goober
642 }
643
644 // getGooberzCount
645 // return the amount of goobers minted
646 //
647 access(all)
648 fun getGooberzCount(): UInt64{
649 return self.totalSupply
650 }
651
652 // getAvailableGooberzCount
653 // returns the amount of currently available goobers for minting
654 //
655 access(all)
656 fun getAvailableGooberzCount(): UInt64{
657 return UInt64(self.gooberPool.length)
658 }
659
660 // isGooberzPoolEmpty
661 // returns a bool to indicate whether or not there is a goober to mint
662 //
663 access(all)
664 fun isGooberzPoolEmpty(): Bool{
665 return self.gooberPool.length > 0
666 }
667
668 // listMintedGoobers
669 // list all minted goobers
670 //
671 access(all)
672 fun listMintedGoobers(): [GooberStruct]{
673 return self.mintedGoobers
674 }
675
676 // listMintedGoobersPage
677 // List minted goobers paged
678 // Param page - indicates the page of the result set
679 // Param page size - indicates the maximum size of the resultset
680 // returns an array of GooberStructs
681 //
682 access(all)
683 fun listMintedGoobersPaged(page: UInt32, pageSize: UInt32): [GooberStruct]{
684 var it: UInt32 = 0
685 var retValues: [GooberStruct] = []
686 let len: Int = self.mintedGoobers.length
687 while it < pageSize{
688 let pointer: UInt32 = page * pageSize + it
689 if pointer < UInt32(len){
690 retValues.append(self.mintedGoobers[pointer])
691 }
692 it = it + 1
693 }
694 return retValues
695 }
696
697 // getGooberPrice
698 // return the goober price
699 //
700 access(all)
701 fun getGooberPrice(): UFix64{
702 if self.gooberPool.length > 0{
703 return self.gooberPool[self.firstGooberInPoolIndex].price
704 }
705 return UFix64(0)
706 }
707
708 // getContractAddress
709 // returns address to smart contract
710 //
711 access(all)
712 fun getContractAddress(): Address{
713 return self.account.address
714 }
715
716 // init function of the smart contract
717 //
718 init(){
719
720 // Initialize the total supply
721 self.totalSupply = 0
722
723 // Initialize the firstGooberInPoolIndex variable
724 self.firstGooberInPoolIndex = 0
725
726 // Init collections
727 self.CollectionStoragePath = /storage/GooberzPartyFolksCollection
728 self.CollectionPublicPath = /public/GooberzPartyFolksCollectionPublic
729
730 // init & save Admin resource to Admin collection
731 self.AdminStoragePath = /storage/GooberzPartyFolksAdmin
732 self.account.storage.save<@Admin>(<-create Admin(), to: self.AdminStoragePath)
733
734 // Initialize global variables
735 self.gooberRegister = []
736 self.gooberPool = []
737 self.mintedGoobersIndex ={}
738 self.mintedGoobers = []
739 self.giveaways ={}
740 }
741}
742