Smart Contract
InceptionMinter
A.83ed64a1d4f3833f.InceptionMinter
1// SPDX-License-Identifier: MIT
2
3import InceptionAvatar from 0x83ed64a1d4f3833f
4import FungibleToken from 0xf233dcee88fe0abe
5import NonFungibleToken from 0x1d7e57aa55817448
6import DapperUtilityCoin from 0xead892083b3e2c6c
7import FlowUtilityToken from 0xead892083b3e2c6c
8import InceptionCrystal from 0x83ed64a1d4f3833f
9import InceptionBlackBox from 0x83ed64a1d4f3833f
10
11pub contract InceptionMinter {
12
13 pub event ContractInitialized()
14
15 pub let AdminStoragePath: StoragePath
16 pub var tipMintPriceInDuc: UFix64
17 pub var tipMintPriceInFlow: UFix64
18
19 pub var preSaleMintLimitPerTx: UInt64
20 pub var tipSaleLimitPerTx: UInt64
21
22 access(self) var whitelistedAccounts: {Address: UInt64}
23 access(self) var publicMintedAccounts: {Address: UInt64}
24 access(self) var tipMintedAccounts: {Address: UInt64}
25 access(self) var usdTipTracker: {Address: UFix64}
26 access(self) var flowTipTracker: {Address: UFix64}
27
28 pub fun tipMintWithDUC(buyer: Address, setID: UInt64, paymentVault: @FungibleToken.Vault, merchantAccount: Address, numberOfTokens: UInt64) {
29 pre {
30 UInt64(self.tipMintedAccounts[buyer] ?? 0) + numberOfTokens <= 5:
31 "You've tipped too much. Please wait for the next tip sale."
32 numberOfTokens <= InceptionMinter.tipSaleLimitPerTx:
33 "purchaseAmount too large"
34 paymentVault.balance >= UFix64(numberOfTokens) * InceptionMinter.tipMintPriceInDuc:
35 "Insufficient payment amount."
36 paymentVault.getType() == Type<@DapperUtilityCoin.Vault>():
37 "payment type not DapperUtilityCoin.Vault."
38 }
39
40 let admin = self.account.borrow<&InceptionAvatar.Admin>(from: InceptionAvatar.AdminStoragePath)
41 ?? panic("Could not borrow a reference to the InceptionAvatar Admin")
42
43 let set = admin.borrowSet(setID: setID)
44 // Check set availability
45 if (set.getAvailableTemplateIDs().length == 0) { panic("set is empty") }
46 // Check set eligibility
47 if (set.locked) { panic("Set is locked") }
48
49 // Get DUC receiver reference of InceptionAvatar merchant account
50 let merchantDUCReceiverRef = getAccount(merchantAccount).getCapability<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver)
51 assert(merchantDUCReceiverRef.borrow() != nil, message: "Missing or mis-typed merchant DUC receiver")
52 // Deposit DUC to InceptionAvatar merchant account DUC Vault (it's then forwarded to the main DUC contract afterwards)
53 merchantDUCReceiverRef.borrow()!.deposit(from: <-paymentVault)
54
55 // Get buyer collection public to receive InceptionAvatar
56 let recipient = getAccount(buyer)
57 let NFTReceiver = recipient.getCapability(InceptionAvatar.CollectionPublicPath)
58 .borrow<&{NonFungibleToken.CollectionPublic}>()
59 ?? panic("Could not get receiver reference to the NFT Collection")
60
61 // Mint InceptionAvatar NFTs per purchaseAmount
62 var mintCounter = numberOfTokens
63 while(mintCounter > 0) {
64 admin.mintNFT(recipient: NFTReceiver, setID: setID)
65 mintCounter = mintCounter - 1
66 }
67
68 // Add number of mints to tipMintedAccounts
69 InceptionMinter.tipMintedAccounts[buyer] = UInt64(InceptionMinter.tipMintedAccounts[buyer] ?? 0) + numberOfTokens
70
71 // Add amount to tipTracker
72 InceptionMinter.usdTipTracker[buyer] = UFix64(InceptionMinter.usdTipTracker[buyer] ?? 0.00) + UFix64(numberOfTokens) * InceptionMinter.tipMintPriceInDuc
73
74 // Hidden gem from the brotherhood of tinkers for your generosity
75 if (InceptionBlackBox.mintLimit >= InceptionBlackBox.totalSupply) {
76 let InceptionBlackBoxAdmin = self.account.borrow<&InceptionBlackBox.Admin>(from: InceptionBlackBox.AdminStoragePath)
77 ?? panic("Could not borrow a reference to the InceptionBlackBox Admin")
78
79 let InceptionBlackBoxReceiver = recipient.getCapability(InceptionBlackBox.CollectionPublicPath)
80 .borrow<&{NonFungibleToken.CollectionPublic}>()
81 ?? panic("Could not get receiver reference to the InceptionBlackBox Collection")
82
83 var blackBoxMintCounter = numberOfTokens
84 while(blackBoxMintCounter > 0) {
85 InceptionBlackBoxAdmin.mintInceptionBlackBox(recipient: InceptionBlackBoxReceiver)
86 blackBoxMintCounter = blackBoxMintCounter - 1
87 }
88 }
89 }
90
91 pub fun tipMintWithFUT(buyer: Address, setID: UInt64, paymentVault: @FungibleToken.Vault, merchantAccount: Address, numberOfTokens: UInt64) {
92 pre {
93 UInt64(self.tipMintedAccounts[buyer] ?? 0) + numberOfTokens < 10:
94 "You've tipped too much. Please wait for the next tip sale."
95 numberOfTokens <= InceptionMinter.tipSaleLimitPerTx:
96 "purchaseAmount too large"
97 paymentVault.balance >= UFix64(numberOfTokens) * InceptionMinter.tipMintPriceInFlow:
98 "Insufficient payment amount."
99 paymentVault.getType() == Type<@FlowUtilityToken.Vault>():
100 "payment type not FlowUtilityToken.Vault."
101 }
102
103 let admin = self.account.borrow<&InceptionAvatar.Admin>(from: InceptionAvatar.AdminStoragePath)
104 ?? panic("Could not borrow a reference to the InceptionAvatar Admin")
105
106 let set = admin.borrowSet(setID: setID)
107 // Check set availability
108 if (set.getAvailableTemplateIDs().length == 0) { panic("set is empty") }
109 // Check set eligibility
110 if (set.locked) { panic("Set is locked") }
111 if (set.isPublic) { panic("Cannot mint public set with mintPrivateNFTWithFUT") }
112
113 // Get FUT receiver reference of InceptionAvatar merchant account
114 let merchantFUTReceiverRef = getAccount(merchantAccount).getCapability<&{FungibleToken.Receiver}>(/public/flowUtilityTokenReceiver)
115 assert(merchantFUTReceiverRef.borrow() != nil, message: "Missing or mis-typed merchant FUT receiver")
116 // Deposit FUT to InceptionAvatar merchant account FUT Vault (it's then forwarded to the main FUT contract afterwards)
117 merchantFUTReceiverRef.borrow()!.deposit(from: <-paymentVault)
118
119 // Get buyer collection public to receive InceptionAvatar
120 let recipient = getAccount(buyer)
121 let NFTReceiver = recipient.getCapability(InceptionAvatar.CollectionPublicPath)
122 .borrow<&{NonFungibleToken.CollectionPublic}>()
123 ?? panic("Could not get receiver reference to the NFT Collection")
124
125 // Mint InceptionAvatar NFTs per purchaseAmount
126 var mintCounter = numberOfTokens
127 while(mintCounter > 0) {
128 admin.mintNFT(recipient: NFTReceiver, setID: setID)
129 mintCounter = mintCounter - 1
130 }
131
132 // Add number of mints to tipMintedAccounts
133 InceptionMinter.tipMintedAccounts[buyer] = UInt64(InceptionMinter.tipMintedAccounts[buyer] ?? 0) + numberOfTokens
134
135 // Add amount to tipTracker
136 InceptionMinter.flowTipTracker[buyer] = UFix64(InceptionMinter.flowTipTracker[buyer] ?? 0.00) + UFix64(numberOfTokens) * InceptionMinter.tipMintPriceInFlow
137
138 // Hidden gem from the brotherhood of tinkers for your generosity
139 if (InceptionBlackBox.mintLimit >= InceptionBlackBox.totalSupply) {
140 let InceptionBlackBoxAdmin = self.account.borrow<&InceptionBlackBox.Admin>(from: InceptionBlackBox.AdminStoragePath)
141 ?? panic("Could not borrow a reference to the InceptionBlackBox Admin")
142
143 let InceptionBlackBoxReceiver = recipient.getCapability(InceptionBlackBox.CollectionPublicPath)
144 .borrow<&{NonFungibleToken.CollectionPublic}>()
145 ?? panic("Could not get receiver reference to the InceptionBlackBox Collection")
146
147 var blackBoxMintCounter = numberOfTokens
148 while(blackBoxMintCounter > 0) {
149 InceptionBlackBoxAdmin.mintInceptionBlackBox(recipient: InceptionBlackBoxReceiver)
150 blackBoxMintCounter = blackBoxMintCounter - 1
151 }
152 }
153 }
154
155 pub fun mintInceptionBlackBoxWithInceptionCrystal(buyer: Address, paymentVault: @InceptionCrystal.Collection) {
156 pre {
157 UInt64(paymentVault.getIDs().length) == InceptionBlackBox.crystalPrice:
158 "incorrect crystal payment"
159 }
160
161 let InceptionBlackBoxAdmin = self.account.borrow<&InceptionBlackBox.Admin>(from: InceptionBlackBox.AdminStoragePath)
162 ?? panic("Could not borrow a reference to the InceptionBlackBox Admin")
163
164 let recipient = getAccount(buyer)
165 let InceptionBlackBoxReceiver = recipient.getCapability(InceptionBlackBox.CollectionPublicPath)
166 .borrow<&{NonFungibleToken.CollectionPublic}>()
167 ?? panic("Could not get receiver reference to the InceptionBlackBox Collection")
168
169 InceptionBlackBoxAdmin.mintInceptionBlackBox(recipient: InceptionBlackBoxReceiver)
170
171 destroy <- paymentVault
172 }
173
174 pub fun whitelistFreeMint(buyer: Address, setID: UInt64, numberOfTokens: UInt64) {
175 pre {
176 InceptionMinter.whitelistedAccounts[buyer]! >= 1:
177 "Requesting account is not whitelisted"
178 numberOfTokens <= InceptionMinter.preSaleMintLimitPerTx:
179 "purchaseAmount too large"
180 InceptionMinter.whitelistedAccounts[buyer]! >= numberOfTokens:
181 "purchaseAmount exeeds allowed whitelist spots"
182 }
183
184 let admin = self.account.borrow<&InceptionAvatar.Admin>(from: InceptionAvatar.AdminStoragePath)
185 ?? panic("Could not borrow a reference to the InceptionAvatar Admin")
186
187 let set = admin.borrowSet(setID: setID)
188 // Check set availability
189 if (set.getAvailableTemplateIDs().length == 0) { panic("set is empty") }
190 // Check set eligibility
191 if (set.locked) { panic("Set is locked") }
192
193 // Get buyer collection public to receive InceptionAvatar
194 let recipient = getAccount(buyer)
195 let NFTReceiver = recipient.getCapability(InceptionAvatar.CollectionPublicPath)
196 .borrow<&{NonFungibleToken.CollectionPublic}>()
197 ?? panic("Could not get receiver reference to the NFT Collection")
198
199 // Validate buyer's DUC receiver
200 let buyerDUCReceiverRef = getAccount(buyer).getCapability<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver)
201 assert(buyerDUCReceiverRef.borrow() != nil, message: "Missing or mis-typed buyer DUC receiver")
202
203 // Mint InceptionAvatar NFTs per purchaseAmount
204 var mintCounter = numberOfTokens
205 while(mintCounter > 0) {
206 admin.mintNFT(recipient: NFTReceiver, setID: setID)
207 mintCounter = mintCounter - 1
208 }
209
210 // Empty whitelist spot
211 if (InceptionMinter.whitelistedAccounts[buyer]! - numberOfTokens == 0) {
212 InceptionMinter.whitelistedAccounts.remove(key: buyer)
213 } else {
214 InceptionMinter.whitelistedAccounts[buyer] = InceptionMinter.whitelistedAccounts[buyer]! - numberOfTokens
215 }
216 }
217
218 // 1 for each outcast
219 pub fun publicFreeMint(buyer: Address, setID: UInt64) {
220 pre {
221 !self.publicMintedAccounts.containsKey(buyer):
222 "Requesting account has already minted"
223
224 getCurrentBlock().timestamp >= 1663797540.00:
225 "Not time yet"
226 }
227
228 let admin = self.account.borrow<&InceptionAvatar.Admin>(from: InceptionAvatar.AdminStoragePath)
229 ?? panic("Could not borrow a reference to the InceptionAvatar Admin")
230
231 let set = admin.borrowSet(setID: setID)
232 // Check set availability
233 if (set.getAvailableTemplateIDs().length == 0) { panic("set is empty") }
234 // Check set eligibility
235 if (set.locked) { panic("Set is locked") }
236
237 // Get buyer collection public to receive InceptionAvatar
238 let recipient = getAccount(buyer)
239 let NFTReceiver = recipient.getCapability(InceptionAvatar.CollectionPublicPath)
240 .borrow<&{NonFungibleToken.CollectionPublic}>()
241 ?? panic("Could not get receiver reference to the NFT Collection")
242
243 // Validate buyer's DUC receiver
244 let buyerDUCReceiverRef = getAccount(buyer).getCapability<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver)
245 assert(buyerDUCReceiverRef.borrow() != nil, message: "Missing or mis-typed buyer DUC receiver")
246
247 // Mint InceptionAvatar NFT to recipient
248 admin.mintNFT(recipient: NFTReceiver, setID: setID)
249
250 // Add wallet address to minted list
251 self.publicMintedAccounts[buyer] = 1
252 }
253
254 pub resource Admin {
255 pub fun addWhiteListAddress(address: Address, amount: UInt64) {
256 pre {
257 amount <= 10:
258 "Unable to allocate more than 10 whitelist spots"
259 InceptionMinter.whitelistedAccounts[address] == nil:
260 "Provided Address is already whitelisted"
261 }
262 InceptionMinter.whitelistedAccounts[address] = amount
263 }
264
265 pub fun removeWhiteListAddress(address: Address) {
266 pre {
267 InceptionMinter.whitelistedAccounts[address] != nil:
268 "Provided Address is not whitelisted"
269 }
270 InceptionMinter.whitelistedAccounts.remove(key: address)
271 }
272
273 pub fun pruneWhitelist() {
274 InceptionMinter.whitelistedAccounts = {}
275 }
276
277 pub fun updateWhiteListAddressAmount(address: Address, amount: UInt64) {
278 pre {
279 InceptionMinter.whitelistedAccounts[address] != nil:
280 "Provided Address is not whitelisted"
281 }
282 InceptionMinter.whitelistedAccounts[address] = amount
283 }
284
285 pub fun updateTipSalePriceInDUC(price: UFix64) {
286 InceptionMinter.tipMintPriceInDuc = price
287 }
288
289 pub fun updateTipSalePriceInFlow(price: UFix64) {
290 InceptionMinter.tipMintPriceInFlow = price
291 }
292
293 pub fun getDucTipJar(): {Address: UFix64} {
294 return InceptionMinter.usdTipTracker
295 }
296
297 pub fun getFlowTipJar(): {Address: UFix64} {
298 return InceptionMinter.flowTipTracker
299 }
300
301 pub fun pruneAccount(address: Address) {
302 if InceptionMinter.tipMintedAccounts.containsKey(address) {
303 InceptionMinter.tipMintedAccounts.remove(key: address)
304 }
305
306 if InceptionMinter.whitelistedAccounts.containsKey(address) {
307 InceptionMinter.whitelistedAccounts.remove(key: address)
308 }
309
310 if InceptionMinter.publicMintedAccounts.containsKey(address) {
311 InceptionMinter.publicMintedAccounts.remove(key: address)
312 }
313 }
314 }
315
316 pub fun getWhitelistedAccounts(): {Address: UInt64} {
317 return InceptionMinter.whitelistedAccounts
318 }
319
320 pub fun getWhitelistedEntriesByAddress(address: Address): UInt64 {
321 return InceptionMinter.whitelistedAccounts[address] ?? 0
322 }
323
324 pub fun getTipMintAccounts(): {Address: UInt64} {
325 return InceptionMinter.tipMintedAccounts
326 }
327
328 pub fun getTipMintCountPerAccount(address: Address): UInt64 {
329 return InceptionMinter.tipMintedAccounts[address] ?? 0
330 }
331
332 pub fun getPublicMintCountPerAccount(address: Address): UInt64 {
333 return InceptionMinter.publicMintedAccounts[address] ?? 0
334 }
335
336 init() {
337 self.AdminStoragePath = /storage/InceptionAvatarWhitelistMinterAdmin
338
339 self.preSaleMintLimitPerTx = 4
340 self.tipSaleLimitPerTx = 5
341
342 self.tipMintPriceInDuc = 20.00
343 self.tipMintPriceInFlow = 12.00
344
345 self.whitelistedAccounts = {}
346 self.publicMintedAccounts = {}
347
348 self.tipMintedAccounts = {}
349 self.usdTipTracker = {}
350 self.flowTipTracker = {}
351
352 let admin <- create Admin()
353 self.account.save(<-admin, to: self.AdminStoragePath)
354
355 emit ContractInitialized()
356 }
357}