Smart Contract

PackOpener

A.a49cc0ee46c54bfb.PackOpener

Deployed

1d ago
Feb 26, 2026, 09:43:52 PM UTC

Dependents

0 imports
1import MotoGPAdmin from 0xa49cc0ee46c54bfb
2import MotoGPPack from 0xa49cc0ee46c54bfb
3import MotoGPCard from 0xa49cc0ee46c54bfb
4import NonFungibleToken from 0x1d7e57aa55817448
5import ContractVersion from 0xa49cc0ee46c54bfb
6
7// Contract for managing pack opening.
8//
9// A PackOpener Collection is created when a user authorizes a tx that saves a PackOpener Collection in the user's storage.
10// The user authorises transfer of a pack to the pack opener.
11// The admin accesses the pack opener to open the pack, which deposits the cards into the user's
12// card collection and destroys the pack.
13//
14pub contract PackOpener: ContractVersion {
15
16    pub fun getVersion(): String {
17        return "1.0.0"
18    }
19
20    pub event Withdraw(id: UInt64, from: Address?)
21    pub event Deposit(id: UInt64, to: Address?)
22    pub event PackOpened(packId: UInt64, packType: UInt64, cardIDs:[UInt64], serials: [UInt64])
23
24    pub resource interface IPackOpenerPublic {
25        pub fun openPack(adminRef: &MotoGPAdmin.Admin, id: UInt64, cardIDs: [UInt64], serials: [UInt64])
26        pub fun deposit(token: @MotoGPPack.NFT)
27        pub fun getIDs(): [UInt64]
28        pub fun borrowPack(id: UInt64): &MotoGPPack.NFT?
29    }
30
31    pub let packOpenerStoragePath: StoragePath
32    pub let packOpenerPublicPath: PublicPath
33
34    pub resource Collection: IPackOpenerPublic {
35
36        access(self) let packMap: @{UInt64: MotoGPPack.NFT}
37        access(self) let cardCollectionCap: Capability<&MotoGPCard.Collection{MotoGPCard.ICardCollectionPublic}>
38
39        pub fun getIDs(): [UInt64] {
40            return self.packMap.keys
41        }
42
43        pub fun deposit(token: @MotoGPPack.NFT) {
44            let id: UInt64 = token.id
45            let oldToken <- self.packMap[id] <- token
46            if self.owner?.address != nil {
47                emit Deposit(id: id, to: self.owner?.address)
48            }
49            destroy oldToken
50        }
51
52        // The withdraw method is not part of IPackOpenerPublic interface, and can only be accessed by the PackOpener collection owner
53        //
54        pub fun withdraw(withdrawID: UInt64): @MotoGPPack.NFT {
55            let token <- self.packMap.remove(key: withdrawID) ?? panic("MotoGPPack not found and can't be removed")
56            emit Withdraw(id: token.id, from: self.owner?.address)
57            return <-token
58        }
59
60        // The openPack method requires a admin reference as argument to open the pack
61        //
62        pub fun openPack(adminRef: &MotoGPAdmin.Admin, id: UInt64, cardIDs: [UInt64], serials: [UInt64]) {
63            pre {
64                adminRef != nil : "adminRef is nil"
65                cardIDs.length == serials.length : "cardIDs and serials are not same length"
66                UInt64(cardIDs.length) == UInt64(3) : "cardsIDs.length is not 3"
67            }
68
69            let cardCollectionRef = self.cardCollectionCap.borrow()!
70            let pack <- self.withdraw(withdrawID: id)
71            var tempCardCollection <- MotoGPCard.createEmptyCollection()
72            let numberOfCards: UInt64 = UInt64(cardIDs.length)
73
74            var i: UInt64 = 0
75            while i < numberOfCards {
76                let tempCardID = cardIDs[i]
77                let tempSerial = serials[i]
78                let newCard <- MotoGPCard.createNFT(cardID: tempCardID, serial: tempSerial)
79                tempCardCollection.deposit(token: <-newCard)
80                i = i + (1 as UInt64)
81            }
82            cardCollectionRef.depositBatch(cardCollection: <-tempCardCollection)
83
84            emit PackOpened(packId: id, packType: pack.packInfo.packType, cardIDs: cardIDs, serials: serials)
85
86            destroy pack
87        }
88
89        pub fun borrowPack(id: UInt64): &MotoGPPack.NFT? {
90            return &self.packMap[id] as &MotoGPPack.NFT?
91        }
92
93        init(_cardCollectionCap: Capability<&MotoGPCard.Collection{MotoGPCard.ICardCollectionPublic}>){
94            self.packMap <- {}
95            self.cardCollectionCap = _cardCollectionCap
96        }
97
98        destroy(){
99            destroy self.packMap
100        }
101    }
102
103    pub fun createEmptyCollection(cardCollectionCap: Capability<&MotoGPCard.Collection{MotoGPCard.ICardCollectionPublic}>): @Collection {
104        return <- create Collection(_cardCollectionCap: cardCollectionCap)
105    }
106
107    init(){
108        self.packOpenerStoragePath = /storage/motogpPackOpenerCollection
109        self.packOpenerPublicPath = /public/motogpPackOpenerCollection
110    }
111
112}