@flowtyio/flow-contracts 0.1.0-beta.8 → 0.1.0
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/FungibleTokenSwitchboard.cdc +360 -0
- package/contracts/MetadataViews.cdc +79 -6
- package/contracts/NonFungibleToken.cdc +17 -10
- package/contracts/TokenForwarding.cdc +19 -11
- package/contracts/capability-cache/CapabilityCache.cdc +97 -0
- package/contracts/dapper/TopShot.cdc +323 -259
- package/contracts/dapper/TopShotLocking.cdc +41 -15
- package/contracts/dapper/offers/DapperOffersV2.cdc +46 -43
- package/contracts/dapper/offers/OffersV2.cdc +40 -56
- package/contracts/dapper/offers/Resolver.cdc +20 -13
- package/contracts/emerald-city/FLOAT.cdc +259 -254
- package/contracts/example/ExampleNFT.cdc +2 -2
- package/contracts/find/FindViews.cdc +357 -353
- package/contracts/flow-utils/ScopedFTProviders.cdc +5 -2
- package/contracts/flow-utils/ScopedNFTProviders.cdc +6 -2
- package/contracts/flowty-drops/ContractManager.cdc +73 -0
- package/contracts/flowty-drops/DropFactory.cdc +75 -0
- package/contracts/flowty-drops/DropTypes.cdc +282 -0
- package/contracts/flowty-drops/FlowtyActiveCheckers.cdc +113 -0
- package/contracts/flowty-drops/FlowtyAddressVerifiers.cdc +64 -0
- package/contracts/flowty-drops/FlowtyDrops.cdc +461 -0
- package/contracts/flowty-drops/FlowtyPricers.cdc +48 -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 +57 -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 +140 -0
- package/contracts/flowty-drops/nft/OpenEditionNFT.cdc +42 -0
- package/contracts/flowty-drops/nft/OpenEditionTemplate.cdc +54 -0
- package/contracts/flowty-drops/nft/UniversalCollection.cdc +29 -0
- package/contracts/fungible-token-router/FungibleTokenRouter.cdc +103 -0
- package/contracts/hybrid-custody/CapabilityDelegator.cdc +28 -26
- package/contracts/hybrid-custody/CapabilityFactory.cdc +20 -18
- package/contracts/hybrid-custody/CapabilityFilter.cdc +41 -24
- package/contracts/hybrid-custody/HybridCustody.cdc +303 -242
- package/contracts/hybrid-custody/factories/FTAllFactory.cdc +16 -4
- package/contracts/hybrid-custody/factories/FTBalanceFactory.cdc +16 -4
- package/contracts/hybrid-custody/factories/FTProviderFactory.cdc +17 -5
- package/contracts/hybrid-custody/factories/FTReceiverBalanceFactory.cdc +16 -4
- package/contracts/hybrid-custody/factories/FTReceiverFactory.cdc +16 -4
- package/contracts/hybrid-custody/factories/FTVaultFactory.cdc +46 -0
- package/contracts/hybrid-custody/factories/NFTCollectionFactory.cdc +45 -0
- package/contracts/hybrid-custody/factories/NFTCollectionPublicFactory.cdc +16 -4
- package/contracts/hybrid-custody/factories/NFTProviderAndCollectionFactory.cdc +22 -0
- package/contracts/hybrid-custody/factories/NFTProviderFactory.cdc +16 -4
- package/contracts/lost-and-found/LostAndFound.cdc +21 -17
- package/flow.json +181 -7
- package/package.json +1 -1
- package/contracts/hybrid-custody/factories/NFTProviderAndCollectionPublicFactory.cdc +0 -10
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ Currently, the list includes:
|
|
|
49
49
|
| FTProviderFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
50
50
|
| FTReceiverFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
51
51
|
| NFTCollectionPublicFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
52
|
-
|
|
|
52
|
+
| NFTProviderAndCollectionFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
53
53
|
| NFTProviderFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
|
|
54
54
|
| NFTCatalog | 0x49a7cda3a1eecc29 | 0x324c34e1c517e4db |
|
|
55
55
|
| NFTCatalogAdmin | 0x49a7cda3a1eecc29 | 0x324c34e1c517e4db |
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import "FungibleToken"
|
|
2
|
+
|
|
3
|
+
/// The contract that allows an account to receive payments in multiple fungible
|
|
4
|
+
/// tokens using a single `{FungibleToken.Receiver}` capability.
|
|
5
|
+
/// This capability should ideally be stored at the
|
|
6
|
+
/// `FungibleTokenSwitchboard.ReceiverPublicPath = /public/GenericFTReceiver`
|
|
7
|
+
/// but it can be stored anywhere.
|
|
8
|
+
///
|
|
9
|
+
access(all) contract FungibleTokenSwitchboard {
|
|
10
|
+
|
|
11
|
+
// Storage and Public Paths
|
|
12
|
+
access(all) let StoragePath: StoragePath
|
|
13
|
+
access(all) let PublicPath: PublicPath
|
|
14
|
+
access(all) let ReceiverPublicPath: PublicPath
|
|
15
|
+
|
|
16
|
+
access(all) entitlement Owner
|
|
17
|
+
|
|
18
|
+
/// The event that is emitted when a new vault capability is added to a
|
|
19
|
+
/// switchboard resource.
|
|
20
|
+
///
|
|
21
|
+
access(all) event VaultCapabilityAdded(type: Type, switchboardOwner: Address?,
|
|
22
|
+
capabilityOwner: Address?)
|
|
23
|
+
|
|
24
|
+
/// The event that is emitted when a vault capability is removed from a
|
|
25
|
+
/// switchboard resource.
|
|
26
|
+
///
|
|
27
|
+
access(all) event VaultCapabilityRemoved(type: Type, switchboardOwner: Address?,
|
|
28
|
+
capabilityOwner: Address?)
|
|
29
|
+
|
|
30
|
+
/// The event that is emitted when a deposit can not be completed.
|
|
31
|
+
///
|
|
32
|
+
access(all) event NotCompletedDeposit(type: Type, amount: UFix64,
|
|
33
|
+
switchboardOwner: Address?)
|
|
34
|
+
|
|
35
|
+
/// The interface that enforces the method to allow anyone to check on the
|
|
36
|
+
/// available capabilities of a switchboard resource and also exposes the
|
|
37
|
+
/// deposit methods to deposit funds on it.
|
|
38
|
+
///
|
|
39
|
+
access(all) resource interface SwitchboardPublic {
|
|
40
|
+
access(all) view fun getVaultTypesWithAddress(): {Type: Address}
|
|
41
|
+
access(all) view fun getSupportedVaultTypes(): {Type: Bool}
|
|
42
|
+
access(all) view fun isSupportedVaultType(type: Type): Bool
|
|
43
|
+
access(all) fun deposit(from: @{FungibleToken.Vault})
|
|
44
|
+
access(all) fun safeDeposit(from: @{FungibleToken.Vault}): @{FungibleToken.Vault}?
|
|
45
|
+
access(all) view fun safeBorrowByType(type: Type): &{FungibleToken.Receiver}?
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// The resource that stores the multiple fungible token receiver
|
|
49
|
+
/// capabilities, allowing the owner to add and remove them and anyone to
|
|
50
|
+
/// deposit any fungible token among the available types.
|
|
51
|
+
///
|
|
52
|
+
access(all) resource Switchboard: FungibleToken.Receiver, SwitchboardPublic {
|
|
53
|
+
|
|
54
|
+
/// Dictionary holding the fungible token receiver capabilities,
|
|
55
|
+
/// indexed by the fungible token vault type.
|
|
56
|
+
///
|
|
57
|
+
access(contract) var receiverCapabilities: {Type: Capability<&{FungibleToken.Receiver}>}
|
|
58
|
+
|
|
59
|
+
/// Adds a new fungible token receiver capability to the switchboard
|
|
60
|
+
/// resource.
|
|
61
|
+
///
|
|
62
|
+
/// @param capability: The capability to expose a certain fungible
|
|
63
|
+
/// token vault deposit function through `{FungibleToken.Receiver}` that
|
|
64
|
+
/// will be added to the switchboard.
|
|
65
|
+
///
|
|
66
|
+
access(Owner) fun addNewVault(capability: Capability<&{FungibleToken.Receiver}>) {
|
|
67
|
+
// Borrow a reference to the vault pointed to by the capability we
|
|
68
|
+
// want to store inside the switchboard
|
|
69
|
+
let vaultRef = capability.borrow()
|
|
70
|
+
?? panic ("Cannot borrow reference to vault from capability")
|
|
71
|
+
// Check if there is a previous capability for this token, if not
|
|
72
|
+
if (self.receiverCapabilities[vaultRef.getType()] == nil) {
|
|
73
|
+
// use the vault reference type as key for storing the
|
|
74
|
+
// capability and then
|
|
75
|
+
self.receiverCapabilities[vaultRef.getType()] = capability
|
|
76
|
+
// emit the event that indicates that a new capability has been
|
|
77
|
+
// added
|
|
78
|
+
emit VaultCapabilityAdded(type: vaultRef.getType(),
|
|
79
|
+
switchboardOwner: self.owner?.address,
|
|
80
|
+
capabilityOwner: capability.address)
|
|
81
|
+
} else {
|
|
82
|
+
// If there was already a capability for that token, panic
|
|
83
|
+
panic("There is already a vault in the Switchboard for this token")
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// Adds a number of new fungible token receiver capabilities by using
|
|
88
|
+
/// the paths where they are stored.
|
|
89
|
+
///
|
|
90
|
+
/// @param paths: The paths where the public capabilities are stored.
|
|
91
|
+
/// @param address: The address of the owner of the capabilities.
|
|
92
|
+
///
|
|
93
|
+
access(Owner) fun addNewVaultsByPath(paths: [PublicPath], address: Address) {
|
|
94
|
+
// Get the account where the public capabilities are stored
|
|
95
|
+
let owner = getAccount(address)
|
|
96
|
+
// For each path, get the saved capability and store it
|
|
97
|
+
// into the switchboard's receiver capabilities dictionary
|
|
98
|
+
for path in paths {
|
|
99
|
+
let capability = owner.capabilities.get<&{FungibleToken.Receiver}>(path)
|
|
100
|
+
// Borrow a reference to the vault pointed to by the capability
|
|
101
|
+
// we want to store inside the switchboard
|
|
102
|
+
// If the vault was borrowed successfully...
|
|
103
|
+
if let vaultRef = capability.borrow() {
|
|
104
|
+
// ...and if there is no previous capability added for that token
|
|
105
|
+
if (self.receiverCapabilities[vaultRef!.getType()] == nil) {
|
|
106
|
+
// Use the vault reference type as key for storing the
|
|
107
|
+
// capability
|
|
108
|
+
self.receiverCapabilities[vaultRef!.getType()] = capability
|
|
109
|
+
// and emit the event that indicates that a new
|
|
110
|
+
// capability has been added
|
|
111
|
+
emit VaultCapabilityAdded(type: vaultRef.getType(),
|
|
112
|
+
switchboardOwner: self.owner?.address,
|
|
113
|
+
capabilityOwner: address,
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/// Adds a new fungible token receiver capability to the switchboard
|
|
121
|
+
/// resource specifying which `Type` of `@{FungibleToken.Vault}` can be
|
|
122
|
+
/// deposited to it. Use it to include in your switchboard "wrapper"
|
|
123
|
+
/// receivers such as a `@TokenForwarding.Forwarder`. It can also be
|
|
124
|
+
/// used to overwrite the type attached to a certain capability without
|
|
125
|
+
/// having to remove that capability first.
|
|
126
|
+
///
|
|
127
|
+
/// @param capability: The capability to expose a certain fungible
|
|
128
|
+
/// token vault deposit function through `{FungibleToken.Receiver}` that
|
|
129
|
+
/// will be added to the switchboard.
|
|
130
|
+
///
|
|
131
|
+
/// @param type: The type of fungible token that can be deposited to that
|
|
132
|
+
/// capability, rather than the `Type` from the reference borrowed from
|
|
133
|
+
/// said capability
|
|
134
|
+
///
|
|
135
|
+
access(Owner) fun addNewVaultWrapper(capability: Capability<&{FungibleToken.Receiver}>,
|
|
136
|
+
type: Type) {
|
|
137
|
+
// Check if the capability is working
|
|
138
|
+
assert(capability.check(), message: "The passed capability is not valid")
|
|
139
|
+
// Use the type parameter as key for the capability
|
|
140
|
+
self.receiverCapabilities[type] = capability
|
|
141
|
+
// emit the event that indicates that a new capability has been
|
|
142
|
+
// added
|
|
143
|
+
emit VaultCapabilityAdded(
|
|
144
|
+
type: type,
|
|
145
|
+
switchboardOwner: self.owner?.address,
|
|
146
|
+
capabilityOwner: capability.address,
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/// Adds zero or more new fungible token receiver capabilities to the
|
|
151
|
+
/// switchboard resource specifying which `Type`s of `@{FungibleToken.Vault}`s
|
|
152
|
+
/// can be deposited to it. Use it to include in your switchboard "wrapper"
|
|
153
|
+
/// receivers such as a `@TokenForwarding.Forwarder`. It can also be
|
|
154
|
+
/// used to overwrite the types attached to certain capabilities without
|
|
155
|
+
/// having to remove those capabilities first.
|
|
156
|
+
///
|
|
157
|
+
/// @param paths: The paths where the public capabilities are stored.
|
|
158
|
+
/// @param types: The types of the fungible token to be deposited on each path.
|
|
159
|
+
/// @param address: The address of the owner of the capabilities.
|
|
160
|
+
///
|
|
161
|
+
access(Owner) fun addNewVaultWrappersByPath(paths: [PublicPath], types: [Type],
|
|
162
|
+
address: Address) {
|
|
163
|
+
// Get the account where the public capabilities are stored
|
|
164
|
+
let owner = getAccount(address)
|
|
165
|
+
// For each path, get the saved capability and store it
|
|
166
|
+
// into the switchboard's receiver capabilities dictionary
|
|
167
|
+
for i, path in paths {
|
|
168
|
+
let capability = owner.capabilities.get<&{FungibleToken.Receiver}>(path)
|
|
169
|
+
// Borrow a reference to the vault pointed to by the capability
|
|
170
|
+
// we want to store inside the switchboard
|
|
171
|
+
// If the vault was borrowed successfully...
|
|
172
|
+
if let vaultRef = capability.borrow() {
|
|
173
|
+
// Use the vault reference type as key for storing the capability
|
|
174
|
+
self.receiverCapabilities[types[i]] = capability
|
|
175
|
+
// and emit the event that indicates that a new capability has been added
|
|
176
|
+
emit VaultCapabilityAdded(
|
|
177
|
+
type: types[i],
|
|
178
|
+
switchboardOwner: self.owner?.address,
|
|
179
|
+
capabilityOwner: address,
|
|
180
|
+
)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/// Removes a fungible token receiver capability from the switchboard
|
|
186
|
+
/// resource.
|
|
187
|
+
///
|
|
188
|
+
/// @param capability: The capability to a fungible token vault to be
|
|
189
|
+
/// removed from the switchboard.
|
|
190
|
+
///
|
|
191
|
+
access(Owner) fun removeVault(capability: Capability<&{FungibleToken.Receiver}>) {
|
|
192
|
+
// Borrow a reference to the vault pointed to by the capability we
|
|
193
|
+
// want to remove from the switchboard
|
|
194
|
+
let vaultRef = capability.borrow()
|
|
195
|
+
?? panic ("Cannot borrow reference to vault from capability")
|
|
196
|
+
// Use the vault reference to find the capability to remove
|
|
197
|
+
self.receiverCapabilities.remove(key: vaultRef.getType())
|
|
198
|
+
// Emit the event that indicates that a new capability has been
|
|
199
|
+
// removed
|
|
200
|
+
emit VaultCapabilityRemoved(
|
|
201
|
+
type: vaultRef.getType(),
|
|
202
|
+
switchboardOwner: self.owner?.address,
|
|
203
|
+
capabilityOwner: capability.address,
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/// Takes a fungible token vault and routes it to the proper fungible
|
|
208
|
+
/// token receiver capability for depositing it.
|
|
209
|
+
///
|
|
210
|
+
/// @param from: The deposited fungible token vault resource.
|
|
211
|
+
///
|
|
212
|
+
access(all) fun deposit(from: @{FungibleToken.Vault}) {
|
|
213
|
+
// Get the capability from the ones stored at the switchboard
|
|
214
|
+
let depositedVaultCapability = self.receiverCapabilities[from.getType()]
|
|
215
|
+
?? panic ("The deposited vault is not available on this switchboard")
|
|
216
|
+
|
|
217
|
+
// Borrow the reference to the desired vault
|
|
218
|
+
let vaultRef = depositedVaultCapability.borrow()
|
|
219
|
+
?? panic ("Can not borrow a reference to the the vault")
|
|
220
|
+
|
|
221
|
+
vaultRef.deposit(from: <-from)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/// Takes a fungible token vault and tries to route it to the proper
|
|
225
|
+
/// fungible token receiver capability for depositing the funds,
|
|
226
|
+
/// avoiding panicking if the vault is not available.
|
|
227
|
+
///
|
|
228
|
+
/// @param vaultType: The type of the ft vault that wants to be
|
|
229
|
+
/// deposited.
|
|
230
|
+
///
|
|
231
|
+
/// @return The deposited fungible token vault resource, without the
|
|
232
|
+
/// funds if the deposit was successful, or still containing the funds
|
|
233
|
+
/// if the reference to the needed vault was not found.
|
|
234
|
+
///
|
|
235
|
+
access(all) fun safeDeposit(from: @{FungibleToken.Vault}): @{FungibleToken.Vault}? {
|
|
236
|
+
// Try to get the proper vault capability from the switchboard
|
|
237
|
+
// If the desired vault is present on the switchboard...
|
|
238
|
+
if let depositedVaultCapability = self.receiverCapabilities[from.getType()] {
|
|
239
|
+
// We try to borrow a reference to the vault from the capability
|
|
240
|
+
// If we can borrow a reference to the vault...
|
|
241
|
+
if let vaultRef = depositedVaultCapability.borrow() {
|
|
242
|
+
// We deposit the funds on said vault
|
|
243
|
+
vaultRef.deposit(from: <-from.withdraw(amount: from.balance))
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// if deposit failed for some reason
|
|
247
|
+
if from.balance > 0.0 {
|
|
248
|
+
emit NotCompletedDeposit(
|
|
249
|
+
type: from.getType(),
|
|
250
|
+
amount: from.balance,
|
|
251
|
+
switchboardOwner: self.owner?.address,
|
|
252
|
+
)
|
|
253
|
+
return <-from
|
|
254
|
+
}
|
|
255
|
+
destroy from
|
|
256
|
+
return nil
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/// Checks that the capability tied to a type is valid
|
|
260
|
+
///
|
|
261
|
+
/// @param vaultType: The type of the ft vault whose capability needs to be checked
|
|
262
|
+
///
|
|
263
|
+
/// @return a boolean marking the capability for a type as valid or not
|
|
264
|
+
access(all) view fun checkReceiverByType(type: Type): Bool {
|
|
265
|
+
if self.receiverCapabilities[type] == nil {
|
|
266
|
+
return false
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return self.receiverCapabilities[type]!.check()
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/// Gets the receiver assigned to a provided vault type.
|
|
273
|
+
/// This is necessary because without it, it is not possible to look under the hood and see if a capability
|
|
274
|
+
/// is of an expected type or not. This helps guard against infinitely chained TokenForwarding or other invalid
|
|
275
|
+
/// malicious kinds of updates that could prevent listings from being made that are valid on storefronts.
|
|
276
|
+
///
|
|
277
|
+
/// @param vaultType: The type of the ft vault whose capability needs to be checked
|
|
278
|
+
///
|
|
279
|
+
/// @return an optional receiver capability for consumers of the switchboard to check/validate on their own
|
|
280
|
+
access(all) view fun safeBorrowByType(type: Type): &{FungibleToken.Receiver}? {
|
|
281
|
+
if !self.checkReceiverByType(type: type) {
|
|
282
|
+
return nil
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return self.receiverCapabilities[type]!.borrow()
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/// A getter function to know which tokens a certain switchboard
|
|
289
|
+
/// resource is prepared to receive along with the address where
|
|
290
|
+
/// those tokens will be deposited.
|
|
291
|
+
///
|
|
292
|
+
/// @return A dictionary mapping the `{FungibleToken.Receiver}`
|
|
293
|
+
/// type to the receiver owner's address
|
|
294
|
+
///
|
|
295
|
+
access(all) view fun getVaultTypesWithAddress(): {Type: Address} {
|
|
296
|
+
let effectiveTypesWithAddress: {Type: Address} = {}
|
|
297
|
+
// Check if each capability is live
|
|
298
|
+
for vaultType in self.receiverCapabilities.keys {
|
|
299
|
+
if self.receiverCapabilities[vaultType]!.check() {
|
|
300
|
+
// and attach it to the owner's address
|
|
301
|
+
effectiveTypesWithAddress[vaultType] = self.receiverCapabilities[vaultType]!.address
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return effectiveTypesWithAddress
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/// A getter function that returns the token types supported by this resource,
|
|
308
|
+
/// which can be deposited using the 'deposit' function.
|
|
309
|
+
///
|
|
310
|
+
/// @return Dictionary of FT types that can be deposited.
|
|
311
|
+
access(all) view fun getSupportedVaultTypes(): {Type: Bool} {
|
|
312
|
+
let supportedVaults: {Type: Bool} = {}
|
|
313
|
+
for receiverType in self.receiverCapabilities.keys {
|
|
314
|
+
if self.receiverCapabilities[receiverType]!.check() {
|
|
315
|
+
if receiverType.isSubtype(of: Type<@{FungibleToken.Vault}>()) {
|
|
316
|
+
supportedVaults[receiverType] = true
|
|
317
|
+
}
|
|
318
|
+
if receiverType.isSubtype(of: Type<@{FungibleToken.Receiver}>()) {
|
|
319
|
+
let receiverRef = self.receiverCapabilities[receiverType]!.borrow()!
|
|
320
|
+
let subReceiverSupportedTypes = receiverRef.getSupportedVaultTypes()
|
|
321
|
+
for subReceiverType in subReceiverSupportedTypes.keys {
|
|
322
|
+
if subReceiverType.isSubtype(of: Type<@{FungibleToken.Vault}>()) {
|
|
323
|
+
supportedVaults[subReceiverType] = true
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return supportedVaults
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/// Returns whether or not the given type is accepted by the Receiver
|
|
333
|
+
/// A vault that can accept any type should just return true by default
|
|
334
|
+
access(all) view fun isSupportedVaultType(type: Type): Bool {
|
|
335
|
+
let supportedVaults = self.getSupportedVaultTypes()
|
|
336
|
+
if let supported = supportedVaults[type] {
|
|
337
|
+
return supported
|
|
338
|
+
} else { return false }
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
init() {
|
|
342
|
+
// Initialize the capabilities dictionary
|
|
343
|
+
self.receiverCapabilities = {}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/// Function that allows to create a new blank switchboard. A user must call
|
|
349
|
+
/// this function and store the returned resource in their storage.
|
|
350
|
+
///
|
|
351
|
+
access(all) fun createSwitchboard(): @Switchboard {
|
|
352
|
+
return <-create Switchboard()
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
init() {
|
|
356
|
+
self.StoragePath = /storage/fungibleTokenSwitchboard
|
|
357
|
+
self.PublicPath = /public/fungibleTokenSwitchboardPublic
|
|
358
|
+
self.ReceiverPublicPath = /public/GenericFTReceiver
|
|
359
|
+
}
|
|
360
|
+
}
|
|
@@ -126,8 +126,32 @@ access(all) contract MetadataViews {
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
///
|
|
130
|
-
///
|
|
129
|
+
/// A struct to represent a generic URI. May be used to represent the URI of
|
|
130
|
+
/// the NFT where the type of URI is not able to be determined (i.e. HTTP,
|
|
131
|
+
/// IPFS, etc.)
|
|
132
|
+
///
|
|
133
|
+
access(all) struct URI: File {
|
|
134
|
+
/// The base URI prefix, if any. Not needed for all URIs, but helpful
|
|
135
|
+
/// for some use cases For example, updating a whole NFT collection's
|
|
136
|
+
/// image host easily
|
|
137
|
+
///
|
|
138
|
+
access(all) let baseURI: String?
|
|
139
|
+
/// The URI string value
|
|
140
|
+
/// NOTE: this is set on init as a concatenation of the baseURI and the
|
|
141
|
+
/// value if baseURI != nil
|
|
142
|
+
///
|
|
143
|
+
access(self) let value: String
|
|
144
|
+
|
|
145
|
+
access(all) view fun uri(): String {
|
|
146
|
+
return self.value
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
init(baseURI: String?, value: String) {
|
|
150
|
+
self.baseURI = baseURI
|
|
151
|
+
self.value = baseURI != nil ? baseURI!.concat(value) : value
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
131
155
|
access(all) struct Media {
|
|
132
156
|
|
|
133
157
|
/// File for the media
|
|
@@ -185,7 +209,7 @@ access(all) contract MetadataViews {
|
|
|
185
209
|
/// Helper to get License in a typesafe way
|
|
186
210
|
///
|
|
187
211
|
/// @param viewResolver: A reference to the resolver resource
|
|
188
|
-
/// @return
|
|
212
|
+
/// @return An optional License struct
|
|
189
213
|
///
|
|
190
214
|
access(all) fun getLicense(_ viewResolver: &{ViewResolver.Resolver}) : License? {
|
|
191
215
|
if let view = viewResolver.resolveView(Type<License>()) {
|
|
@@ -212,7 +236,7 @@ access(all) contract MetadataViews {
|
|
|
212
236
|
/// Helper to get ExternalURL in a typesafe way
|
|
213
237
|
///
|
|
214
238
|
/// @param viewResolver: A reference to the resolver resource
|
|
215
|
-
/// @return
|
|
239
|
+
/// @return An optional ExternalURL struct
|
|
216
240
|
///
|
|
217
241
|
access(all) fun getExternalURL(_ viewResolver: &{ViewResolver.Resolver}) : ExternalURL? {
|
|
218
242
|
if let view = viewResolver.resolveView(Type<ExternalURL>()) {
|
|
@@ -665,7 +689,7 @@ access(all) contract MetadataViews {
|
|
|
665
689
|
// Square-sized image to represent this collection.
|
|
666
690
|
access(all) let squareImage: MetadataViews.Media
|
|
667
691
|
|
|
668
|
-
// Banner-sized image for this collection, recommended to have a size near
|
|
692
|
+
// Banner-sized image for this collection, recommended to have a size near 1400x350.
|
|
669
693
|
access(all) let bannerImage: MetadataViews.Media
|
|
670
694
|
|
|
671
695
|
// Social links to reach this collection's social homepages.
|
|
@@ -703,4 +727,53 @@ access(all) contract MetadataViews {
|
|
|
703
727
|
}
|
|
704
728
|
return nil
|
|
705
729
|
}
|
|
706
|
-
|
|
730
|
+
/// This view may be used by Cadence-native projects to define their
|
|
731
|
+
/// contract- and token-level metadata according to EVM-compatible formats.
|
|
732
|
+
/// Several ERC standards (e.g. ERC20, ERC721, etc.) expose name and symbol
|
|
733
|
+
/// values to define assets as well as contract- & token-level metadata view
|
|
734
|
+
/// `tokenURI(uint256)` and `contractURI()` methods. This view enables
|
|
735
|
+
/// Cadence projects to define in their own contracts how they would like
|
|
736
|
+
/// their metadata to be defined when bridged to EVM.
|
|
737
|
+
///
|
|
738
|
+
access(all) struct EVMBridgedMetadata {
|
|
739
|
+
|
|
740
|
+
/// The name of the asset
|
|
741
|
+
///
|
|
742
|
+
access(all) let name: String
|
|
743
|
+
|
|
744
|
+
/// The symbol of the asset
|
|
745
|
+
///
|
|
746
|
+
access(all) let symbol: String
|
|
747
|
+
|
|
748
|
+
/// The URI of the asset - this can either be contract-level or
|
|
749
|
+
/// token-level URI depending on where the metadata is resolved. It
|
|
750
|
+
/// is recommended to reference EVM metadata standards for how to best
|
|
751
|
+
/// prepare your view's formatted value.
|
|
752
|
+
///
|
|
753
|
+
/// For example, while you may choose to take advantage of onchain
|
|
754
|
+
/// metadata, as is the case for most Cadence NFTs, you may also choose
|
|
755
|
+
/// to represent your asset's metadata in IPFS and assign this value as
|
|
756
|
+
/// an IPFSFile struct pointing to that IPFS file. Alternatively, you
|
|
757
|
+
/// may serialize your NFT's metadata and assign it as a JSON string
|
|
758
|
+
/// data URL representating the NFT's onchain metadata at the time this
|
|
759
|
+
/// view is resolved.
|
|
760
|
+
///
|
|
761
|
+
access(all) let uri: {File}
|
|
762
|
+
|
|
763
|
+
init(name: String, symbol: String, uri: {File}) {
|
|
764
|
+
self.name = name
|
|
765
|
+
self.symbol = symbol
|
|
766
|
+
self.uri = uri
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
access(all) fun getEVMBridgedMetadata(_ viewResolver: &{ViewResolver.Resolver}) : EVMBridgedMetadata? {
|
|
771
|
+
if let view = viewResolver.resolveView(Type<EVMBridgedMetadata>()) {
|
|
772
|
+
if let v = view as? EVMBridgedMetadata {
|
|
773
|
+
return v
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
return nil
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
}
|
|
@@ -49,9 +49,6 @@ access(all) contract interface NonFungibleToken: ViewResolver {
|
|
|
49
49
|
/// An entitlement for allowing updates and update events for an NFT
|
|
50
50
|
access(all) entitlement Update
|
|
51
51
|
|
|
52
|
-
/// entitlement for owner that grants Withdraw and Update
|
|
53
|
-
access(all) entitlement Owner
|
|
54
|
-
|
|
55
52
|
/// Event that contracts should emit when the metadata of an NFT is updated
|
|
56
53
|
/// It can only be emitted by calling the `emitNFTUpdated` function
|
|
57
54
|
/// with an `Updatable` entitled reference to the NFT that was updated
|
|
@@ -63,7 +60,7 @@ access(all) contract interface NonFungibleToken: ViewResolver {
|
|
|
63
60
|
/// and query the updated metadata from the owners' collections.
|
|
64
61
|
///
|
|
65
62
|
access(all) event Updated(type: String, id: UInt64, uuid: UInt64, owner: Address?)
|
|
66
|
-
access(
|
|
63
|
+
access(all) view fun emitNFTUpdated(_ nftRef: auth(Update) &{NonFungibleToken.NFT})
|
|
67
64
|
{
|
|
68
65
|
emit Updated(type: nftRef.getType().identifier, id: nftRef.id, uuid: nftRef.uuid, owner: nftRef.owner?.address)
|
|
69
66
|
}
|
|
@@ -85,9 +82,6 @@ access(all) contract interface NonFungibleToken: ViewResolver {
|
|
|
85
82
|
///
|
|
86
83
|
access(all) event Deposited(type: String, id: UInt64, uuid: UInt64, to: Address?, collectionUUID: UInt64)
|
|
87
84
|
|
|
88
|
-
/// Included for backwards-compatibility
|
|
89
|
-
access(all) resource interface INFT: NFT {}
|
|
90
|
-
|
|
91
85
|
/// Interface that the NFTs must conform to
|
|
92
86
|
///
|
|
93
87
|
access(all) resource interface NFT: ViewResolver.Resolver {
|
|
@@ -105,6 +99,7 @@ access(all) contract interface NonFungibleToken: ViewResolver {
|
|
|
105
99
|
access(all) fun createEmptyCollection(): @{Collection} {
|
|
106
100
|
post {
|
|
107
101
|
result.getLength() == 0: "The created collection must be empty!"
|
|
102
|
+
result.isSupportedNFTType(type: self.getType()): "The created collection must support this NFT type"
|
|
108
103
|
}
|
|
109
104
|
}
|
|
110
105
|
|
|
@@ -141,7 +136,7 @@ access(all) contract interface NonFungibleToken: ViewResolver {
|
|
|
141
136
|
/// withdraw removes an NFT from the collection and moves it to the caller
|
|
142
137
|
/// It does not specify whether the ID is UUID or not
|
|
143
138
|
/// @param withdrawID: The id of the NFT to withdraw from the collection
|
|
144
|
-
access(Withdraw
|
|
139
|
+
access(Withdraw) fun withdraw(withdrawID: UInt64): @{NFT} {
|
|
145
140
|
post {
|
|
146
141
|
result.id == withdrawID: "The ID of the withdrawn token must be the same as the requested ID"
|
|
147
142
|
emit Withdrawn(type: result.getType().identifier, id: result.id, uuid: result.uuid, from: self.owner?.address, providerUUID: self.uuid)
|
|
@@ -174,6 +169,7 @@ access(all) contract interface NonFungibleToken: ViewResolver {
|
|
|
174
169
|
access(all) fun deposit(token: @{NFT})
|
|
175
170
|
access(all) view fun getLength(): Int
|
|
176
171
|
access(all) view fun getIDs(): [UInt64]
|
|
172
|
+
access(all) fun forEachID(_ f: fun (UInt64): Bool): Void
|
|
177
173
|
access(all) view fun borrowNFT(_ id: UInt64): &{NFT}?
|
|
178
174
|
}
|
|
179
175
|
|
|
@@ -182,6 +178,8 @@ access(all) contract interface NonFungibleToken: ViewResolver {
|
|
|
182
178
|
///
|
|
183
179
|
access(all) resource interface Collection: Provider, Receiver, CollectionPublic, ViewResolver.ResolverCollection {
|
|
184
180
|
|
|
181
|
+
access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
|
|
182
|
+
|
|
185
183
|
/// deposit takes a NFT as an argument and stores it in the collection
|
|
186
184
|
/// @param token: The NFT to deposit into the collection
|
|
187
185
|
access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
|
|
@@ -196,7 +194,16 @@ access(all) contract interface NonFungibleToken: ViewResolver {
|
|
|
196
194
|
|
|
197
195
|
/// Gets the amount of NFTs stored in the collection
|
|
198
196
|
/// @return An integer indicating the size of the collection
|
|
199
|
-
access(all) view fun getLength(): Int
|
|
197
|
+
access(all) view fun getLength(): Int {
|
|
198
|
+
return self.ownedNFTs.length
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/// Allows a given function to iterate through the list
|
|
202
|
+
/// of owned NFT IDs in a collection without first
|
|
203
|
+
/// having to load the entire list into memory
|
|
204
|
+
access(all) fun forEachID(_ f: fun (UInt64): Bool): Void {
|
|
205
|
+
self.ownedNFTs.forEachKey(f)
|
|
206
|
+
}
|
|
200
207
|
|
|
201
208
|
/// Borrows a reference to an NFT stored in the collection
|
|
202
209
|
/// If the NFT with the specified ID is not in the collection,
|
|
@@ -231,4 +238,4 @@ access(all) contract interface NonFungibleToken: ViewResolver {
|
|
|
231
238
|
result.getIDs().length == 0: "The created collection must be empty!"
|
|
232
239
|
}
|
|
233
240
|
}
|
|
234
|
-
}
|
|
241
|
+
}
|
|
@@ -16,29 +16,37 @@ their tokens to.
|
|
|
16
16
|
|
|
17
17
|
import "FungibleToken"
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
access(all) contract TokenForwarding {
|
|
20
20
|
|
|
21
21
|
// Event that is emitted when tokens are deposited to the target receiver
|
|
22
|
-
|
|
22
|
+
access(all) event ForwardedDeposit(amount: UFix64, from: Address?)
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
access(all) resource interface ForwarderPublic {
|
|
25
|
+
access(all) fun check(): Bool
|
|
26
|
+
access(all) fun safeBorrow(): &{FungibleToken.Receiver}?
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
access(all) resource Forwarder: FungibleToken.Receiver, ForwarderPublic {
|
|
30
30
|
|
|
31
31
|
// This is where the deposited tokens will be sent.
|
|
32
32
|
// The type indicates that it is a reference to a receiver
|
|
33
33
|
//
|
|
34
34
|
access(self) var recipient: Capability
|
|
35
35
|
|
|
36
|
+
access(all) view fun getSupportedVaultTypes(): {Type: Bool} {
|
|
37
|
+
return {}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
access(all) view fun isSupportedVaultType(type: Type): Bool {
|
|
41
|
+
return true
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
// deposit
|
|
37
45
|
//
|
|
38
46
|
// Function that takes a Vault object as an argument and forwards
|
|
39
47
|
// it to the recipient's Vault using the stored reference
|
|
40
48
|
//
|
|
41
|
-
|
|
49
|
+
access(all) fun deposit(from: @{FungibleToken.Vault}) {
|
|
42
50
|
let receiverRef = self.recipient.borrow<&{FungibleToken.Receiver}>()!
|
|
43
51
|
|
|
44
52
|
let balance = from.balance
|
|
@@ -48,17 +56,17 @@ pub contract TokenForwarding {
|
|
|
48
56
|
emit ForwardedDeposit(amount: balance, from: self.owner?.address)
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
|
|
59
|
+
access(all) fun check(): Bool {
|
|
52
60
|
return self.recipient.check<&{FungibleToken.Receiver}>()
|
|
53
61
|
}
|
|
54
62
|
|
|
55
|
-
|
|
63
|
+
access(all) fun safeBorrow(): &{FungibleToken.Receiver}? {
|
|
56
64
|
return self.recipient.borrow<&{FungibleToken.Receiver}>()
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
// changeRecipient changes the recipient of the forwarder to the provided recipient
|
|
60
68
|
//
|
|
61
|
-
|
|
69
|
+
access(all) fun changeRecipient(_ newRecipient: Capability) {
|
|
62
70
|
pre {
|
|
63
71
|
newRecipient.borrow<&{FungibleToken.Receiver}>() != nil: "Could not borrow Receiver reference from the Capability"
|
|
64
72
|
}
|
|
@@ -75,7 +83,7 @@ pub contract TokenForwarding {
|
|
|
75
83
|
|
|
76
84
|
// createNewForwarder creates a new Forwarder reference with the provided recipient
|
|
77
85
|
//
|
|
78
|
-
|
|
86
|
+
access(all) fun createNewForwarder(recipient: Capability): @Forwarder {
|
|
79
87
|
return <-create Forwarder(recipient: recipient)
|
|
80
88
|
}
|
|
81
89
|
}
|