@flowtyio/flow-contracts 0.1.0-beta.9 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/contracts/FungibleTokenSwitchboard.cdc +360 -0
  3. package/contracts/MetadataViews.cdc +79 -6
  4. package/contracts/NonFungibleToken.cdc +17 -10
  5. package/contracts/capability-cache/CapabilityCache.cdc +97 -0
  6. package/contracts/dapper/TopShot.cdc +323 -259
  7. package/contracts/dapper/TopShotLocking.cdc +41 -15
  8. package/contracts/dapper/offers/DapperOffersV2.cdc +46 -43
  9. package/contracts/dapper/offers/OffersV2.cdc +40 -56
  10. package/contracts/dapper/offers/Resolver.cdc +20 -13
  11. package/contracts/emerald-city/FLOAT.cdc +259 -254
  12. package/contracts/evm/CrossVMNFT.cdc +50 -0
  13. package/contracts/evm/EVM.cdc +851 -0
  14. package/contracts/evm/FlowEVMBridgeConfig.cdc +454 -0
  15. package/contracts/evm/FlowEVMBridgeHandlerInterfaces.cdc +163 -0
  16. package/contracts/evm/FlowEVMBridgeHandlers.cdc +230 -0
  17. package/contracts/evm/FlowEVMBridgeUtils.cdc +1303 -0
  18. package/contracts/evm/IBridgePermissions.cdc +19 -0
  19. package/contracts/evm/ICrossVM.cdc +12 -0
  20. package/contracts/evm/ICrossVMAsset.cdc +19 -0
  21. package/contracts/evm/Serialize.cdc +141 -0
  22. package/contracts/evm/SerializeMetadata.cdc +221 -0
  23. package/contracts/example/ExampleNFT.cdc +2 -2
  24. package/contracts/find/FindViews.cdc +357 -353
  25. package/contracts/flow-utils/ScopedFTProviders.cdc +5 -2
  26. package/contracts/flow-utils/ScopedNFTProviders.cdc +6 -2
  27. package/contracts/flowty-drops/ContractManager.cdc +73 -0
  28. package/contracts/flowty-drops/DropFactory.cdc +75 -0
  29. package/contracts/flowty-drops/DropTypes.cdc +282 -0
  30. package/contracts/flowty-drops/FlowtyActiveCheckers.cdc +113 -0
  31. package/contracts/flowty-drops/FlowtyAddressVerifiers.cdc +64 -0
  32. package/contracts/flowty-drops/FlowtyDrops.cdc +461 -0
  33. package/contracts/flowty-drops/FlowtyPricers.cdc +48 -0
  34. package/contracts/flowty-drops/initializers/ContractBorrower.cdc +14 -0
  35. package/contracts/flowty-drops/initializers/ContractInitializer.cdc +7 -0
  36. package/contracts/flowty-drops/initializers/OpenEditionInitializer.cdc +57 -0
  37. package/contracts/flowty-drops/nft/BaseCollection.cdc +97 -0
  38. package/contracts/flowty-drops/nft/BaseNFT.cdc +107 -0
  39. package/contracts/flowty-drops/nft/ContractFactory.cdc +13 -0
  40. package/contracts/flowty-drops/nft/ContractFactoryTemplate.cdc +48 -0
  41. package/contracts/flowty-drops/nft/NFTMetadata.cdc +140 -0
  42. package/contracts/flowty-drops/nft/OpenEditionNFT.cdc +42 -0
  43. package/contracts/flowty-drops/nft/OpenEditionTemplate.cdc +54 -0
  44. package/contracts/flowty-drops/nft/UniversalCollection.cdc +29 -0
  45. package/contracts/fungible-token-router/FungibleTokenRouter.cdc +103 -0
  46. package/contracts/hybrid-custody/CapabilityDelegator.cdc +28 -26
  47. package/contracts/hybrid-custody/CapabilityFactory.cdc +20 -18
  48. package/contracts/hybrid-custody/CapabilityFilter.cdc +41 -24
  49. package/contracts/hybrid-custody/HybridCustody.cdc +303 -242
  50. package/contracts/hybrid-custody/factories/FTAllFactory.cdc +16 -4
  51. package/contracts/hybrid-custody/factories/FTBalanceFactory.cdc +16 -4
  52. package/contracts/hybrid-custody/factories/FTProviderFactory.cdc +17 -5
  53. package/contracts/hybrid-custody/factories/FTReceiverBalanceFactory.cdc +16 -4
  54. package/contracts/hybrid-custody/factories/FTReceiverFactory.cdc +16 -4
  55. package/contracts/hybrid-custody/factories/FTVaultFactory.cdc +46 -0
  56. package/contracts/hybrid-custody/factories/NFTCollectionFactory.cdc +45 -0
  57. package/contracts/hybrid-custody/factories/NFTCollectionPublicFactory.cdc +16 -4
  58. package/contracts/hybrid-custody/factories/NFTProviderAndCollectionFactory.cdc +22 -0
  59. package/contracts/hybrid-custody/factories/NFTProviderFactory.cdc +16 -4
  60. package/contracts/lost-and-found/LostAndFound.cdc +21 -17
  61. package/contracts/tokens/USDCFlow.cdc +232 -0
  62. package/flow.json +278 -7
  63. package/package.json +1 -1
  64. package/contracts/hybrid-custody/factories/NFTProviderAndCollectionPublicFactory.cdc +0 -10
@@ -57,6 +57,10 @@ access(all) contract ScopedFTProviders {
57
57
  self.expiration = expiration
58
58
  }
59
59
 
60
+ access(all) fun getProviderType(): Type {
61
+ return self.provider.borrow()!.getType()
62
+ }
63
+
60
64
  access(all) fun check(): Bool {
61
65
  return self.provider.check()
62
66
  }
@@ -86,7 +90,7 @@ access(all) contract ScopedFTProviders {
86
90
  return self.canWithdraw(amount)
87
91
  }
88
92
 
89
- access(FungibleToken.Withdraw | FungibleToken.Withdraw) fun withdraw(amount: UFix64): @{FungibleToken.Vault} {
93
+ access(FungibleToken.Withdraw) fun withdraw(amount: UFix64): @{FungibleToken.Vault} {
90
94
  pre {
91
95
  !self.isExpired(): "provider has expired"
92
96
  }
@@ -122,4 +126,3 @@ access(all) contract ScopedFTProviders {
122
126
  return <- create ScopedFTProvider(provider: provider, filters: filters, expiration: expiration)
123
127
  }
124
128
  }
125
-
@@ -102,7 +102,11 @@ access(all) contract ScopedNFTProviders {
102
102
  return false
103
103
  }
104
104
 
105
- let nft = self.provider.borrow()!.borrowNFT(id)
105
+ if !self.provider.check() {
106
+ return false
107
+ }
108
+
109
+ let nft: &{NonFungibleToken.NFT}? = self.provider.borrow()!.borrowNFT(id)
106
110
  if nft == nil {
107
111
  return false
108
112
  }
@@ -121,7 +125,7 @@ access(all) contract ScopedNFTProviders {
121
125
  return self.provider.check()
122
126
  }
123
127
 
124
- access(NonFungibleToken.Withdraw | NonFungibleToken.Owner) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
128
+ access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
125
129
  pre {
126
130
  !self.isExpired(): "provider has expired"
127
131
  }
@@ -0,0 +1,73 @@
1
+ import "FlowToken"
2
+ import "FungibleToken"
3
+ import "FungibleTokenRouter"
4
+
5
+ access(all) contract ContractManager {
6
+ access(all) let StoragePath: StoragePath
7
+ access(all) let PublicPath: PublicPath
8
+
9
+ access(all) entitlement Manage
10
+
11
+ access(all) resource Manager {
12
+ access(self) let acct: Capability<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>
13
+ access(self) let routerCap: Capability<auth(FungibleTokenRouter.Owner) &FungibleTokenRouter.Router>
14
+
15
+ access(all) let data: {String: AnyStruct}
16
+ access(all) let resources: @{String: AnyResource}
17
+
18
+ access(Manage) fun borrowContractAccount(): auth(Contracts) &Account {
19
+ return self.acct.borrow()!
20
+ }
21
+
22
+ access(Manage) fun addOverride(type: Type, addr: Address) {
23
+ let router = self.routerCap.borrow() ?? panic("fungible token router is not valid")
24
+ router.addOverride(type: type, addr: addr)
25
+ }
26
+
27
+ access(Manage) fun getSwitchboard(): auth(FungibleTokenRouter.Owner) &FungibleTokenRouter.Router {
28
+ return self.routerCap.borrow()!
29
+ }
30
+
31
+ access(all) fun addFlowTokensToAccount(_ tokens: @FlowToken.Vault) {
32
+ self.acct.borrow()!.storage.borrow<&{FungibleToken.Receiver}>(from: /storage/flowTokenVault)!.deposit(from: <-tokens)
33
+ }
34
+
35
+ access(all) fun getAccount(): &Account {
36
+ return getAccount(self.acct.address)
37
+ }
38
+
39
+ init(tokens: @FlowToken.Vault, defaultRouterAddress: Address) {
40
+ pre {
41
+ tokens.balance >= 0.001: "minimum balance of 0.001 required for initialization"
42
+ }
43
+
44
+ let acct = Account(payer: ContractManager.account)
45
+ self.acct = acct.capabilities.account.issue<auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account>()
46
+ assert(self.acct.check(), message: "failed to setup account capability")
47
+
48
+ acct.storage.borrow<&{FungibleToken.Receiver}>(from: /storage/flowTokenVault)!.deposit(from: <-tokens)
49
+
50
+ let router <- FungibleTokenRouter.createRouter(defaultAddress: defaultRouterAddress)
51
+ acct.storage.save(<-router, to: FungibleTokenRouter.StoragePath)
52
+
53
+ let receiver = acct.capabilities.storage.issue<&{FungibleToken.Receiver}>(FungibleTokenRouter.StoragePath)
54
+ assert(receiver.check(), message: "invalid switchboard receiver capability")
55
+ acct.capabilities.publish(receiver, at: FungibleTokenRouter.PublicPath)
56
+
57
+ self.routerCap = acct.capabilities.storage.issue<auth(FungibleTokenRouter.Owner) &FungibleTokenRouter.Router>(FungibleTokenRouter.StoragePath)
58
+
59
+ self.data = {}
60
+ self.resources <- {}
61
+ }
62
+ }
63
+
64
+ access(all) fun createManager(tokens: @FlowToken.Vault, defaultRouterAddress: Address): @Manager {
65
+ return <- create Manager(tokens: <- tokens, defaultRouterAddress: defaultRouterAddress)
66
+ }
67
+
68
+ init() {
69
+ let identifier = "ContractManager_".concat(self.account.address.toString())
70
+ self.StoragePath = StoragePath(identifier: identifier)!
71
+ self.PublicPath = PublicPath(identifier: identifier)!
72
+ }
73
+ }
@@ -0,0 +1,75 @@
1
+ import "FungibleToken"
2
+ import "MetadataViews"
3
+
4
+ import "FlowtyDrops"
5
+ import "FlowtyActiveCheckers"
6
+ import "FlowtyAddressVerifiers"
7
+ import "FlowtyPricers"
8
+
9
+ /*
10
+ The DropFactory is a contract that helps create common types of drops
11
+ */
12
+ access(all) contract DropFactory {
13
+ access(all) fun createEndlessOpenEditionDrop(
14
+ price: UFix64,
15
+ paymentTokenType: Type,
16
+ dropDisplay: MetadataViews.Display,
17
+ minterCap: Capability<&{FlowtyDrops.Minter}>,
18
+ nftTypeIdentifier: String
19
+ ): @FlowtyDrops.Drop {
20
+ pre {
21
+ paymentTokenType.isSubtype(of: Type<@{FungibleToken.Vault}>()): "paymentTokenType must be a FungibleToken"
22
+ }
23
+
24
+ // This drop is always on and never ends.
25
+ let activeChecker = FlowtyActiveCheckers.AlwaysOn()
26
+
27
+ // All addresses are allowed to participate
28
+ let addressVerifier = FlowtyAddressVerifiers.AllowAll(maxPerMint: 10)
29
+
30
+ // The cost of each mint is the same, and only permits one token type as payment
31
+ let pricer = FlowtyPricers.FlatPrice(price: price, paymentTokenType: paymentTokenType)
32
+
33
+ let phaseDetails = FlowtyDrops.PhaseDetails(activeChecker: activeChecker, display: nil, pricer: pricer, addressVerifier: addressVerifier)
34
+ let phase <- FlowtyDrops.createPhase(details: phaseDetails)
35
+
36
+
37
+ let nftType = CompositeType(nftTypeIdentifier) ?? panic("invalid nft type identifier")
38
+ let dropDetails = FlowtyDrops.DropDetails(display: dropDisplay, medias: nil, commissionRate: 0.05, nftType: nftTypeIdentifier)
39
+ let drop <- FlowtyDrops.createDrop(details: dropDetails, minterCap: minterCap, phases: <- [<-phase])
40
+
41
+ return <- drop
42
+ }
43
+
44
+ access(all) fun createTimeBasedOpenEditionDrop(
45
+ price: UFix64,
46
+ paymentTokenType: Type,
47
+ dropDisplay: MetadataViews.Display,
48
+ minterCap: Capability<&{FlowtyDrops.Minter}>,
49
+ startUnix: UInt64?,
50
+ endUnix: UInt64?,
51
+ nftTypeIdentifier: String
52
+ ): @FlowtyDrops.Drop {
53
+ pre {
54
+ paymentTokenType.isSubtype(of: Type<@{FungibleToken.Vault}>()): "paymentTokenType must be a FungibleToken"
55
+ }
56
+
57
+ // This ActiveChecker turns on at a set unix timestamp (or is on by default if nil), and ends at the specified end date if provided
58
+ let activeChecker = FlowtyActiveCheckers.TimestampChecker(start: startUnix, end: endUnix)
59
+
60
+ // All addresses are allowed to participate
61
+ let addressVerifier = FlowtyAddressVerifiers.AllowAll(maxPerMint: 10)
62
+
63
+ // The cost of each mint is the same, and only permits one token type as payment
64
+ let pricer = FlowtyPricers.FlatPrice(price: price, paymentTokenType: paymentTokenType)
65
+
66
+ let phaseDetails = FlowtyDrops.PhaseDetails(activeChecker: activeChecker, display: nil, pricer: pricer, addressVerifier: addressVerifier)
67
+ let phase <- FlowtyDrops.createPhase(details: phaseDetails)
68
+
69
+ let nftType = CompositeType(nftTypeIdentifier) ?? panic("invalid nft type identifier")
70
+ let dropDetails = FlowtyDrops.DropDetails(display: dropDisplay, medias: nil, commissionRate: 0.05, nftType: nftTypeIdentifier)
71
+ let drop <- FlowtyDrops.createDrop(details: dropDetails, minterCap: minterCap, phases: <- [<-phase])
72
+
73
+ return <- drop
74
+ }
75
+ }
@@ -0,0 +1,282 @@
1
+ import "FlowtyDrops"
2
+ import "MetadataViews"
3
+ import "ViewResolver"
4
+ import "AddressUtils"
5
+
6
+ access(all) contract DropTypes {
7
+ access(all) struct Display {
8
+ access(all) let name: String
9
+ access(all) let description: String
10
+ access(all) let url: String
11
+
12
+ init(_ display: MetadataViews.Display) {
13
+ self.name = display.name
14
+ self.description = display.description
15
+ self.url = display.thumbnail.uri()
16
+ }
17
+ }
18
+
19
+ access(all) struct Media {
20
+ access(all) let url: String
21
+ access(all) let mediaType: String
22
+
23
+ init(_ media: MetadataViews.Media) {
24
+ self.url = media.file.uri()
25
+ self.mediaType = media.mediaType
26
+ }
27
+ }
28
+
29
+ access(all) struct DropSummary {
30
+ access(all) let id: UInt64
31
+ access(all) let display: Display
32
+ access(all) let medias: [Media]
33
+ access(all) let totalMinted: Int
34
+ access(all) let minterCount: Int
35
+ access(all) let commissionRate: UFix64
36
+ access(all) let nftType: String
37
+
38
+ access(all) let address: Address?
39
+ access(all) let mintedByAddress: Int?
40
+
41
+ access(all) let phases: [PhaseSummary]
42
+
43
+ access(all) let blockTimestamp: UInt64
44
+ access(all) let blockHeight: UInt64
45
+
46
+ init(
47
+ id: UInt64,
48
+ display: MetadataViews.Display,
49
+ medias: MetadataViews.Medias?,
50
+ totalMinted: Int,
51
+ minterCount: Int,
52
+ mintedByAddress: Int?,
53
+ commissionRate: UFix64,
54
+ nftType: Type,
55
+ address: Address?,
56
+ phases: [PhaseSummary]
57
+ ) {
58
+ self.id = id
59
+ self.display = Display(display)
60
+
61
+ self.medias = []
62
+ for m in medias?.items ?? [] {
63
+ self.medias.append(Media(m))
64
+ }
65
+
66
+
67
+ self.totalMinted = totalMinted
68
+ self.commissionRate = commissionRate
69
+ self.minterCount = minterCount
70
+ self.mintedByAddress = mintedByAddress
71
+ self.nftType = nftType.identifier
72
+ self.address = address
73
+ self.phases = phases
74
+
75
+ let b = getCurrentBlock()
76
+ self.blockHeight = b.height
77
+ self.blockTimestamp = UInt64(b.timestamp)
78
+ }
79
+ }
80
+
81
+ access(all) struct Quote {
82
+ access(all) let price: UFix64
83
+ access(all) let quantity: Int
84
+ access(all) let paymentIdentifier: String
85
+ access(all) let minter: Address?
86
+
87
+ init(price: UFix64, quantity: Int, paymentIdentifier: String, minter: Address?) {
88
+ self.price = price
89
+ self.quantity = quantity
90
+ self.paymentIdentifier = paymentIdentifier
91
+ self.minter = minter
92
+ }
93
+ }
94
+
95
+ access(all) struct PhaseSummary {
96
+ access(all) let id: UInt64
97
+ access(all) let index: Int
98
+
99
+ access(all) let activeCheckerType: String
100
+ access(all) let pricerType: String
101
+ access(all) let addressVerifierType: String
102
+
103
+ access(all) let hasStarted: Bool
104
+ access(all) let hasEnded: Bool
105
+ access(all) let start: UInt64?
106
+ access(all) let end: UInt64?
107
+
108
+ access(all) let paymentTypes: [String]
109
+
110
+ access(all) let address: Address?
111
+ access(all) let remainingForAddress: Int?
112
+
113
+ access(all) let quote: Quote?
114
+
115
+ init(
116
+ index: Int,
117
+ phase: &{FlowtyDrops.PhasePublic},
118
+ address: Address?,
119
+ totalMinted: Int?,
120
+ minter: Address?,
121
+ quantity: Int?,
122
+ paymentIdentifier: String?
123
+ ) {
124
+ self.index = index
125
+ self.id = phase.uuid
126
+
127
+ let d: FlowtyDrops.PhaseDetails = phase.getDetails()
128
+ self.activeCheckerType = d.activeChecker.getType().identifier
129
+ self.pricerType = d.pricer.getType().identifier
130
+ self.addressVerifierType = d.addressVerifier.getType().identifier
131
+
132
+ self.hasStarted = d.activeChecker.hasStarted()
133
+ self.hasEnded = d.activeChecker.hasEnded()
134
+ self.start = d.activeChecker.getStart()
135
+ self.end = d.activeChecker.getEnd()
136
+
137
+ self.paymentTypes = []
138
+ for pt in d.pricer.getPaymentTypes() {
139
+ self.paymentTypes.append(pt.identifier)
140
+ }
141
+
142
+ if let addr = address {
143
+ self.address = address
144
+ self.remainingForAddress = d.addressVerifier.remainingForAddress(addr: addr, totalMinted: totalMinted ?? 0)
145
+ } else {
146
+ self.address = nil
147
+ self.remainingForAddress = nil
148
+ }
149
+
150
+ if paymentIdentifier != nil && quantity != nil {
151
+ let price = d.pricer.getPrice(num: quantity!, paymentTokenType: CompositeType(paymentIdentifier!)!, minter: minter)
152
+
153
+ self.quote = Quote(price: price, quantity: quantity!, paymentIdentifier: paymentIdentifier!, minter: minter)
154
+ } else {
155
+ self.quote = nil
156
+ }
157
+ }
158
+ }
159
+
160
+ access(all) fun getDropSummary(nftTypeIdentifier: String, dropID: UInt64, minter: Address?, quantity: Int?, paymentIdentifier: String?): DropSummary? {
161
+ let nftType = CompositeType(nftTypeIdentifier) ?? panic("invalid nft type identifier")
162
+ let segments = nftTypeIdentifier.split(separator: ".")
163
+ let contractAddress = AddressUtils.parseAddress(nftType)!
164
+ let contractName = segments[2]
165
+
166
+ let resolver = getAccount(contractAddress).contracts.borrow<&{ViewResolver}>(name: contractName)
167
+ if resolver == nil {
168
+ return nil
169
+ }
170
+
171
+ let dropResolver = resolver!.resolveContractView(resourceType: nftType, viewType: Type<FlowtyDrops.DropResolver>()) as! FlowtyDrops.DropResolver?
172
+ if dropResolver == nil {
173
+ return nil
174
+ }
175
+
176
+ let container = dropResolver!.borrowContainer()
177
+ if container == nil {
178
+ return nil
179
+ }
180
+
181
+ let drop = container!.borrowDropPublic(id: dropID)
182
+ if drop == nil {
183
+ return nil
184
+ }
185
+
186
+ let dropDetails = drop!.getDetails()
187
+
188
+ let phaseSummaries: [PhaseSummary] = []
189
+ for index, phase in drop!.borrowAllPhases() {
190
+ let summary = PhaseSummary(
191
+ index: index,
192
+ phase: phase,
193
+ address: minter,
194
+ totalMinted: minter != nil ? dropDetails.minters[minter!] : nil,
195
+ minter: minter,
196
+ quantity: quantity,
197
+ paymentIdentifier: paymentIdentifier
198
+ )
199
+ phaseSummaries.append(summary)
200
+ }
201
+
202
+ let dropSummary = DropSummary(
203
+ id: drop!.uuid,
204
+ display: dropDetails.display,
205
+ medias: dropDetails.medias,
206
+ totalMinted: dropDetails.totalMinted,
207
+ minterCount: dropDetails.minters.keys.length,
208
+ mintedByAddress: minter != nil ? dropDetails.minters[minter!] : nil,
209
+ commissionRate: dropDetails.commissionRate,
210
+ nftType: CompositeType(dropDetails.nftType)!,
211
+ address: minter,
212
+ phases: phaseSummaries
213
+ )
214
+
215
+ return dropSummary
216
+ }
217
+
218
+ access(all) fun getAllDropSummaries(nftTypeIdentifier: String, minter: Address?, quantity: Int?, paymentIdentifier: String?): [DropSummary] {
219
+ let nftType = CompositeType(nftTypeIdentifier) ?? panic("invalid nft type identifier")
220
+ let segments = nftTypeIdentifier.split(separator: ".")
221
+ let contractAddress = AddressUtils.parseAddress(nftType)!
222
+ let contractName = segments[2]
223
+
224
+ let resolver = getAccount(contractAddress).contracts.borrow<&{ViewResolver}>(name: contractName)
225
+ if resolver == nil {
226
+ return []
227
+ }
228
+
229
+ let dropResolver = resolver!.resolveContractView(resourceType: nftType, viewType: Type<FlowtyDrops.DropResolver>()) as! FlowtyDrops.DropResolver?
230
+ if dropResolver == nil {
231
+ return []
232
+ }
233
+
234
+ let container = dropResolver!.borrowContainer()
235
+ if container == nil {
236
+ return []
237
+ }
238
+
239
+ let summaries: [DropSummary] = []
240
+ for id in container!.getIDs() {
241
+ let drop = container!.borrowDropPublic(id: id)
242
+ if drop == nil {
243
+ continue
244
+ }
245
+
246
+ let dropDetails = drop!.getDetails()
247
+
248
+ let phaseSummaries: [PhaseSummary] = []
249
+ for index, phase in drop!.borrowAllPhases() {
250
+ let summary = PhaseSummary(
251
+ index: index,
252
+ phase: phase,
253
+ address: minter,
254
+ totalMinted: minter != nil ? dropDetails.minters[minter!] : nil,
255
+ minter: minter,
256
+ quantity: quantity,
257
+ paymentIdentifier: paymentIdentifier
258
+ )
259
+ phaseSummaries.append(summary)
260
+ }
261
+
262
+ if CompositeType(dropDetails.nftType) == nil {
263
+ continue
264
+ }
265
+
266
+ summaries.append(DropSummary(
267
+ id: drop!.uuid,
268
+ display: dropDetails.display,
269
+ medias: dropDetails.medias,
270
+ totalMinted: dropDetails.totalMinted,
271
+ minterCount: dropDetails.minters.keys.length,
272
+ mintedByAddress: minter != nil ? dropDetails.minters[minter!] : nil,
273
+ commissionRate: dropDetails.commissionRate,
274
+ nftType: CompositeType(dropDetails.nftType)!,
275
+ address: minter,
276
+ phases: phaseSummaries
277
+ ))
278
+ }
279
+
280
+ return summaries
281
+ }
282
+ }
@@ -0,0 +1,113 @@
1
+ import "FlowtyDrops"
2
+
3
+ /*
4
+ This contract contains implementations for the FlowtyDrops.ActiveChecker struct interface.
5
+ You can use these implementations, or your own, to configure when a phase in a drop is active
6
+ */
7
+ access(all) contract FlowtyActiveCheckers {
8
+ /*
9
+ The AlwaysOn ActiveChecker is always on and never ends.
10
+ */
11
+ access(all) struct AlwaysOn: FlowtyDrops.ActiveChecker {
12
+ access(all) view fun hasStarted(): Bool {
13
+ return true
14
+ }
15
+
16
+ access(all) view fun hasEnded(): Bool {
17
+ return false
18
+ }
19
+
20
+ access(all) view fun getStart(): UInt64? {
21
+ return nil
22
+ }
23
+
24
+ access(all) view fun getEnd(): UInt64? {
25
+ return nil
26
+ }
27
+ }
28
+
29
+ /*
30
+ The manual checker is used to explicitly toggle a drop.
31
+ This version of checker allows a creator to turn on or off a drop at will
32
+ */
33
+ access(all) struct ManualChecker: FlowtyDrops.ActiveChecker {
34
+ access(self) var started: Bool
35
+ access(self) var ended: Bool
36
+
37
+ access(all) view fun hasStarted(): Bool {
38
+ return self.started
39
+ }
40
+
41
+ access(all) view fun hasEnded(): Bool {
42
+ return self.ended
43
+ }
44
+
45
+ access(all) view fun getStart(): UInt64? {
46
+ return nil
47
+ }
48
+
49
+ access(all) view fun getEnd(): UInt64? {
50
+ return nil
51
+ }
52
+
53
+ access(Mutate) fun setStarted(_ b: Bool) {
54
+ self.started = b
55
+ }
56
+
57
+ access(Mutate) fun setEnded(_ b: Bool) {
58
+ self.ended = b
59
+ }
60
+
61
+ init() {
62
+ self.started = false
63
+ self.ended = false
64
+ }
65
+ }
66
+
67
+ /*
68
+ TimestampChecker uses block timestamps to determine if a phase or drop is live or not.
69
+ A timestamp checker has a start and an end time.
70
+ */
71
+ access(all) struct TimestampChecker: FlowtyDrops.ActiveChecker {
72
+ access(all) var start: UInt64?
73
+ access(all) var end: UInt64?
74
+
75
+
76
+ access(all) view fun hasStarted(): Bool {
77
+ return self.start == nil || UInt64(getCurrentBlock().timestamp) >= self.start!
78
+ }
79
+
80
+ access(all) view fun hasEnded(): Bool {
81
+ if self.end == nil {
82
+ return false
83
+ }
84
+
85
+ return UInt64(getCurrentBlock().timestamp) > self.end!
86
+ }
87
+
88
+ access(all) view fun getStart(): UInt64? {
89
+ return self.start
90
+ }
91
+
92
+ access(all) view fun getEnd(): UInt64? {
93
+ return self.end
94
+ }
95
+
96
+ access(Mutate) fun setStart(start: UInt64?) {
97
+ self.start = start
98
+ }
99
+
100
+ access(Mutate) fun setEnd(end: UInt64?) {
101
+ self.end = end
102
+ }
103
+
104
+ init(start: UInt64?, end: UInt64?) {
105
+ pre {
106
+ start == nil || end == nil || start! < end!: "start must be less than end"
107
+ }
108
+
109
+ self.start = start
110
+ self.end = end
111
+ }
112
+ }
113
+ }
@@ -0,0 +1,64 @@
1
+ import "FlowtyDrops"
2
+
3
+ /*
4
+ This contract contains implementations of the FlowtyDrops.AddressVerifier struct interface
5
+ */
6
+ access(all) contract FlowtyAddressVerifiers {
7
+ /*
8
+ The AllowAll AddressVerifier allows any address to mint without any verification
9
+ */
10
+ access(all) struct AllowAll: FlowtyDrops.AddressVerifier {
11
+ access(all) var maxPerMint: Int
12
+
13
+ access(all) view fun canMint(addr: Address, num: Int, totalMinted: Int, data: {String: AnyStruct}): Bool {
14
+ return num <= self.maxPerMint
15
+ }
16
+
17
+ access(Mutate) fun setMaxPerMint(_ value: Int) {
18
+ self.maxPerMint = value
19
+ }
20
+
21
+ init(maxPerMint: Int) {
22
+ pre {
23
+ maxPerMint > 0: "maxPerMint must be greater than 0"
24
+ }
25
+
26
+ self.maxPerMint = maxPerMint
27
+ }
28
+ }
29
+
30
+ /*
31
+ The AllowList Verifier only lets a configured set of addresses participate in a drop phase. The number
32
+ of mints per address is specified to allow more granular control of what each address is permitted to do.
33
+ */
34
+ access(all) struct AllowList: FlowtyDrops.AddressVerifier {
35
+ access(self) let allowedAddresses: {Address: Int}
36
+
37
+ access(all) view fun canMint(addr: Address, num: Int, totalMinted: Int, data: {String: AnyStruct}): Bool {
38
+ if let allowedMints = self.allowedAddresses[addr] {
39
+ return allowedMints >= num + totalMinted
40
+ }
41
+
42
+ return false
43
+ }
44
+
45
+ access(all) view fun remainingForAddress(addr: Address, totalMinted: Int): Int? {
46
+ if let allowedMints = self.allowedAddresses[addr] {
47
+ return allowedMints - totalMinted
48
+ }
49
+ return nil
50
+ }
51
+
52
+ access(Mutate) fun setAddress(addr: Address, value: Int) {
53
+ self.allowedAddresses[addr] = value
54
+ }
55
+
56
+ access(Mutate) fun removeAddress(addr: Address) {
57
+ self.allowedAddresses.remove(key: addr)
58
+ }
59
+
60
+ init(allowedAddresses: {Address: Int}) {
61
+ self.allowedAddresses = allowedAddresses
62
+ }
63
+ }
64
+ }