Smart Contract

GooberXContract

A.34f2bf4a80bb0f69.GooberXContract

Deployed

18h ago
Feb 27, 2026, 10:55:27 PM UTC

Dependents

0 imports
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