Smart Contract

FantastecPackNFT

A.4bbff461fa8f6192.FantastecPackNFT

Deployed

16h ago
Feb 28, 2026, 02:27:40 AM UTC

Dependents

0 imports
1import Crypto
2import NonFungibleToken from 0x1d7e57aa55817448
3import FantastecNFT from 0x4bbff461fa8f6192
4import IFantastecPackNFT from 0x4bbff461fa8f6192
5import MetadataViews from 0x1d7e57aa55817448
6import ViewResolver from 0x1d7e57aa55817448
7import Burner from 0xf233dcee88fe0abe
8
9access(all) contract FantastecPackNFT: NonFungibleToken, IFantastecPackNFT {
10
11    access(all) var totalSupply: UInt64
12    access(all) let CollectionStoragePath: StoragePath
13    access(all) let CollectionPublicPath: PublicPath
14    access(all) let CollectionIFantastecPackNFTPublicPath: PublicPath
15    access(all) let OperatorStoragePath: StoragePath
16
17    access(contract) let packs: @{UInt64: Pack}
18
19    // from IFantastecPackNFT
20    access(all) event Burned(id: UInt64)
21    // from NonFungibleToken
22    access(all) event ContractInitialized()
23    access(all) event Withdraw(id: UInt64, from: Address?)
24    access(all) event Deposit(id: UInt64, to: Address?)
25    // contract specific
26    access(all) event Minted(id: UInt64)
27
28    access(all) resource FantastecPackNFTOperator: IFantastecPackNFT.IOperator {
29        access(IFantastecPackNFT.Owner) fun mint(packId: UInt64, productId: UInt64): @{IFantastecPackNFT.NFT}{
30            let packNFT <- create NFT(packId: packId, productId: productId)
31            FantastecPackNFT.totalSupply = FantastecPackNFT.totalSupply + 1
32            emit Minted(id: packNFT.id)
33            let pack <- create Pack()
34            FantastecPackNFT.packs[packNFT.id] <-! pack
35            return <- packNFT
36        }
37
38        access(IFantastecPackNFT.Owner) fun open(id: UInt64, recipient: Address) {
39            let pack <- FantastecPackNFT.packs.remove(key: id) ?? panic("cannot find pack with ID ".concat(id.toString()))
40            pack.open(recipient: recipient)
41            FantastecPackNFT.packs[id] <-! pack
42        }
43
44        access(IFantastecPackNFT.Owner) fun addFantastecNFT(id: UInt64, nft: @FantastecNFT.NFT) {
45            let pack <- FantastecPackNFT.packs.remove(key: id) ?? panic("cannot find pack with ID ".concat(id.toString()))
46            pack.addFantastecNFT(nft: <- nft)
47            FantastecPackNFT.packs[id] <-! pack
48        }
49
50        init(){}
51    }
52
53    access(all) resource Pack: IFantastecPackNFT.IFantastecPack {
54        access(all) var ownedNFTs: @{UInt64: FantastecNFT.NFT}
55
56        access(IFantastecPackNFT.Owner) fun open(recipient: Address) {
57            let receiver = getAccount(recipient)
58                .capabilities.get<&{NonFungibleToken.CollectionPublic}>(FantastecNFT.CollectionPublicPath)
59                .borrow()
60                ?? panic("Could not get receiver reference to the NFT Collection - ".concat(recipient.toString()))
61            for key in self.ownedNFTs.keys {
62                let nft <-! self.ownedNFTs.remove(key: key)
63                receiver.deposit(token: <- nft!)
64            }
65        }
66
67        access(all) fun addFantastecNFT(nft: @FantastecNFT.NFT) {
68            let id = nft.id
69            self.ownedNFTs[id] <-! nft
70        }
71
72        init() {
73            self.ownedNFTs <- {}
74        }
75    }
76
77    access(all) resource NFT: IFantastecPackNFT.NFT, Burner.Burnable, ViewResolver.Resolver {
78        access(all) let id: UInt64
79        access(all) let productId: UInt64
80
81        access(contract) fun burnCallback() {
82            FantastecPackNFT.totalSupply = FantastecPackNFT.totalSupply - (1 as UInt64)
83            let pack <- FantastecPackNFT.packs.remove(key: self.id)
84                ?? panic("cannot find pack with ID ".concat(self.id.toString()))
85            destroy pack
86            emit Burned(id: self.id)
87        }
88
89        init(packId: UInt64, productId: UInt64) {
90            self.id = packId
91            self.productId = productId
92        }
93
94        // from MetadataViews.Resolver
95        access(all) view fun getViews(): [Type] {
96            return [
97                Type<MetadataViews.Display>()
98            ]
99        }
100
101        // from MetadataViews.Resolver
102        access(all) view fun resolveView(_ view: Type): AnyStruct? {
103            switch view {
104                case Type<MetadataViews.Display>():
105                    return MetadataViews.Display(
106                        name: "Fantastec Pack",
107                        description: "Reveals Fantstec NFTs when opened",
108                        thumbnail: MetadataViews.HTTPFile(url: self.getThumbnailPath())
109                    )
110            }
111            return nil
112        }
113
114        access(all) view fun getThumbnailPath(): String {
115            return "path/to/thumbnail/".concat(self.id.toString())
116        }
117
118        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { 
119            return <- create Collection()
120        }
121    }
122
123    access(all) resource Collection: IFantastecPackNFT.IFantastecPackNFTCollectionPublic {
124        // dictionary of NFT conforming tokens
125        // NFT is a resource type with an `UInt64` ID field
126        access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
127
128        init () {
129            self.ownedNFTs <- {}
130        }
131
132        // withdraw removes an NFT from the collection and moves it to the caller
133        access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
134            let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
135            emit Withdraw(id: token.id, from: self.owner?.address)
136            return <- token
137        }
138
139        // deposit takes a NFT and adds it to the collections dictionary
140        // and adds the ID to the id array
141        access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
142            let token <- token as! @FantastecPackNFT.NFT
143
144            let id: UInt64 = token.id
145
146            // add the new token to the dictionary which removes the old one
147            let oldToken <- self.ownedNFTs[id] <- token
148            emit Deposit(id: id, to: self.owner?.address)
149
150            destroy oldToken
151        }
152
153        // getIDs returns an array of the IDs that are in the collection
154        access(all) view fun getIDs(): [UInt64] {
155            return self.ownedNFTs.keys
156        }
157
158        // borrowNFT gets a reference to an NFT in the collection
159        // so that the caller can read its metadata and call its methods
160        access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
161            return &self.ownedNFTs[id]
162        }
163
164        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { 
165            return <- create Collection()
166        }
167
168        access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
169            return {
170                Type<@NFT>(): true
171            }
172        }
173
174        access(all) view fun isSupportedNFTType(type: Type): Bool {
175            return type == Type<@NFT>()
176        }
177    }
178
179    access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
180        return <- create Collection()
181    }
182
183    access(all) view fun getContractViews(resourceType: Type?): [Type] {
184        return []
185    }
186
187    access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
188        return nil
189    }
190
191    init(){
192        self.totalSupply = 0
193        self.packs <- {}
194        // Set our named paths
195        self.CollectionStoragePath = /storage/FantastecPackNFTCollection
196        self.CollectionPublicPath = /public/FantastecPackNFTCollection
197        self.CollectionIFantastecPackNFTPublicPath = /public/FantastecPackNFTCollection
198        self.OperatorStoragePath = /storage/FantastecPackNFTOperatorCollection
199
200        // Create a collection to receive Pack NFTs
201        let collection <- create Collection()
202        self.account.storage.save(<-collection, to: self.CollectionStoragePath)
203
204        let cap = self.account.capabilities.storage.issue<&{NonFungibleToken.CollectionPublic, IFantastecPackNFT.IFantastecPackNFTCollectionPublic}>(self.CollectionStoragePath)
205        self.account.capabilities.publish(cap, at: self.CollectionPublicPath)
206
207        // Create a operator to share mint capability with proxy
208        let operator <- create FantastecPackNFTOperator()
209        self.account.storage.save(<-operator, to: self.OperatorStoragePath)
210
211        self.account.capabilities.storage.issue<&{IFantastecPackNFT.IOperator}>(self.OperatorStoragePath)
212    }
213}
214