@flowtyio/flow-contracts 0.1.0-beta.23 → 0.1.0-beta.25
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.
- package/README.md +1 -1
- package/contracts/dapper/offers/DapperOffersV2.cdc +35 -28
- package/contracts/dapper/offers/OffersV2.cdc +13 -30
- package/contracts/dapper/offers/Resolver.cdc +8 -2
- package/contracts/flowty-drops/ContractManager.cdc +47 -0
- package/contracts/flowty-drops/DropFactory.cdc +75 -0
- package/contracts/flowty-drops/DropTypes.cdc +278 -0
- package/contracts/flowty-drops/FlowtyAddressVerifiers.cdc +64 -0
- package/contracts/flowty-drops/FlowtyDrops.cdc +431 -0
- package/contracts/flowty-drops/FlowtyPricers.cdc +48 -0
- package/contracts/flowty-drops/FlowtySwitchers.cdc +113 -0
- package/contracts/flowty-drops/initializers/ContractBorrower.cdc +14 -0
- package/contracts/flowty-drops/initializers/ContractInitializer.cdc +7 -0
- package/contracts/flowty-drops/initializers/OpenEditionInitializer.cdc +58 -0
- package/contracts/flowty-drops/nft/BaseCollection.cdc +97 -0
- package/contracts/flowty-drops/nft/BaseNFT.cdc +107 -0
- package/contracts/flowty-drops/nft/ContractFactory.cdc +13 -0
- package/contracts/flowty-drops/nft/ContractFactoryTemplate.cdc +48 -0
- package/contracts/flowty-drops/nft/NFTMetadata.cdc +119 -0
- package/contracts/flowty-drops/nft/OpenEditionNFT.cdc +41 -0
- package/contracts/flowty-drops/nft/OpenEditionTemplate.cdc +52 -0
- package/contracts/flowty-drops/nft/UniversalCollection.cdc +23 -0
- package/flow.json +139 -3
- package/package.json +1 -1
|
@@ -0,0 +1,278 @@
|
|
|
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 switcherType: 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 = phase.getDetails()
|
|
128
|
+
self.switcherType = d.switcher.getType().identifier
|
|
129
|
+
self.pricerType = d.pricer.getType().identifier
|
|
130
|
+
self.addressVerifierType = d.addressVerifier.getType().identifier
|
|
131
|
+
|
|
132
|
+
self.hasStarted = d.switcher.hasStarted()
|
|
133
|
+
self.hasEnded = d.switcher.hasEnded()
|
|
134
|
+
self.start = d.switcher.getStart()
|
|
135
|
+
self.end = d.switcher.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
|
+
summaries.append(DropSummary(
|
|
263
|
+
id: drop!.uuid,
|
|
264
|
+
display: dropDetails.display,
|
|
265
|
+
medias: dropDetails.medias,
|
|
266
|
+
totalMinted: dropDetails.totalMinted,
|
|
267
|
+
minterCount: dropDetails.minters.keys.length,
|
|
268
|
+
mintedByAddress: minter != nil ? dropDetails.minters[minter!] : nil,
|
|
269
|
+
commissionRate: dropDetails.commissionRate,
|
|
270
|
+
nftType: CompositeType(dropDetails.nftType)!,
|
|
271
|
+
address: minter,
|
|
272
|
+
phases: phaseSummaries
|
|
273
|
+
))
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return summaries
|
|
277
|
+
}
|
|
278
|
+
}
|
|
@@ -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
|
+
}
|