Smart Contract
FantastecPackNFT
A.4bbff461fa8f6192.FantastecPackNFT
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