@flowtyio/flow-contracts 0.1.0-beta.2 → 0.1.0-beta.21

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 (44) hide show
  1. package/contracts/Burner.cdc +44 -0
  2. package/contracts/FlowStorageFees.cdc +15 -15
  3. package/contracts/FlowToken.cdc +29 -78
  4. package/contracts/FungibleToken.cdc +80 -53
  5. package/contracts/FungibleTokenMetadataViews.cdc +13 -25
  6. package/contracts/MetadataViews.cdc +107 -50
  7. package/contracts/NonFungibleToken.cdc +110 -60
  8. package/contracts/TokenForwarding.cdc +19 -11
  9. package/contracts/ViewResolver.cdc +20 -16
  10. package/contracts/dapper/DapperUtilityCoin.cdc +106 -39
  11. package/contracts/dapper/FlowUtilityToken.cdc +107 -40
  12. package/contracts/dapper/TopShot.cdc +323 -259
  13. package/contracts/dapper/TopShotLocking.cdc +41 -15
  14. package/contracts/dapper/offers/DapperOffersV2.cdc +36 -40
  15. package/contracts/dapper/offers/OffersV2.cdc +52 -51
  16. package/contracts/dapper/offers/Resolver.cdc +13 -12
  17. package/contracts/emerald-city/FLOAT.cdc +259 -254
  18. package/contracts/example/ExampleNFT.cdc +419 -0
  19. package/contracts/example/ExampleToken.cdc +302 -0
  20. package/contracts/find/FindViews.cdc +357 -353
  21. package/contracts/flow-utils/AddressUtils.cdc +20 -23
  22. package/contracts/flow-utils/ArrayUtils.cdc +10 -11
  23. package/contracts/flow-utils/ScopedFTProviders.cdc +27 -19
  24. package/contracts/flow-utils/ScopedNFTProviders.cdc +31 -26
  25. package/contracts/flow-utils/StringUtils.cdc +24 -37
  26. package/contracts/hybrid-custody/CapabilityDelegator.cdc +29 -26
  27. package/contracts/hybrid-custody/CapabilityFactory.cdc +21 -18
  28. package/contracts/hybrid-custody/CapabilityFilter.cdc +42 -24
  29. package/contracts/hybrid-custody/HybridCustody.cdc +303 -242
  30. package/contracts/hybrid-custody/factories/FTAllFactory.cdc +16 -4
  31. package/contracts/hybrid-custody/factories/FTBalanceFactory.cdc +16 -4
  32. package/contracts/hybrid-custody/factories/FTProviderFactory.cdc +17 -5
  33. package/contracts/hybrid-custody/factories/FTReceiverBalanceFactory.cdc +16 -4
  34. package/contracts/hybrid-custody/factories/FTReceiverFactory.cdc +16 -4
  35. package/contracts/hybrid-custody/factories/FTVaultFactory.cdc +45 -0
  36. package/contracts/hybrid-custody/factories/NFTCollectionFactory.cdc +45 -0
  37. package/contracts/hybrid-custody/factories/NFTCollectionPublicFactory.cdc +16 -4
  38. package/contracts/hybrid-custody/factories/NFTProviderAndCollectionPublicFactory.cdc +16 -4
  39. package/contracts/hybrid-custody/factories/NFTProviderFactory.cdc +16 -4
  40. package/contracts/lost-and-found/LostAndFound.cdc +14 -14
  41. package/contracts/nft-catalog/NFTCatalog.cdc +60 -64
  42. package/contracts/nft-catalog/NFTCatalogAdmin.cdc +28 -27
  43. package/flow.json +38 -1
  44. package/package.json +1 -1
@@ -2,20 +2,17 @@
2
2
 
3
3
  ## The Flow Non-Fungible Token standard
4
4
 
5
- ## `NonFungibleToken` contract interface
5
+ ## `NonFungibleToken` contract
6
6
 
7
7
  The interface that all Non-Fungible Token contracts should conform to.
8
- If a user wants to deploy a new NFT contract, their contract would need
9
- to implement the NonFungibleToken interface.
8
+ If a user wants to deploy a new NFT contract, their contract should implement
9
+ The types defined here
10
10
 
11
- Their contract must follow all the rules and naming
12
- that the interface specifies.
13
-
14
- ## `NFT` resource
11
+ ## `NFT` resource interface
15
12
 
16
13
  The core resource type that represents an NFT in the smart contract.
17
14
 
18
- ## `Collection` Resource
15
+ ## `Collection` Resource interface
19
16
 
20
17
  The resource that stores a user's NFT collection.
21
18
  It includes a few functions to allow the owner to easily
@@ -26,10 +23,8 @@ move tokens in and out of the collection.
26
23
  These interfaces declare functions with some pre and post conditions
27
24
  that require the Collection to follow certain naming and behavior standards.
28
25
 
29
- They are separate because it gives the user the ability to share a reference
30
- to their Collection that only exposes the fields and functions in one or more
31
- of the interfaces. It also gives users the ability to make custom resources
32
- that implement these interfaces to do various things with the tokens.
26
+ They are separate because it gives developers the ability to define functions
27
+ that can use any type that implements these interfaces
33
28
 
34
29
  By using resources and interfaces, users of NFT smart contracts can send
35
30
  and receive tokens peer-to-peer, without having to interact with a central ledger
@@ -43,16 +38,16 @@ Collection to complete the transfer.
43
38
 
44
39
  import "ViewResolver"
45
40
 
46
- /// The main NFT contract interface. Other NFT contracts will
47
- /// import and implement this interface
41
+ /// The main NFT contract. Other NFT contracts will
42
+ /// import and implement the interfaces defined in this contract
48
43
  ///
49
- access(all) contract NonFungibleToken {
44
+ access(all) contract interface NonFungibleToken: ViewResolver {
50
45
 
51
46
  /// An entitlement for allowing the withdrawal of tokens from a Vault
52
- access(all) entitlement Withdrawable
47
+ access(all) entitlement Withdraw
53
48
 
54
49
  /// An entitlement for allowing updates and update events for an NFT
55
- access(all) entitlement Updatable
50
+ access(all) entitlement Update
56
51
 
57
52
  /// Event that contracts should emit when the metadata of an NFT is updated
58
53
  /// It can only be emitted by calling the `emitNFTUpdated` function
@@ -60,45 +55,67 @@ access(all) contract NonFungibleToken {
60
55
  /// The entitlement prevents spammers from calling this from other users' collections
61
56
  /// because only code within a collection or that has special entitled access
62
57
  /// to the collections methods will be able to get the entitled reference
63
- ///
58
+ ///
64
59
  /// The event makes it so that third-party indexers can monitor the events
65
60
  /// and query the updated metadata from the owners' collections.
66
61
  ///
67
- access(all) event Updated(id: UInt64, uuid: UInt64, owner: Address?, type: String)
68
- access(all) view fun emitNFTUpdated(_ nftRef: auth(Updatable) &{NonFungibleToken.NFT})
62
+ access(all) event Updated(type: String, id: UInt64, uuid: UInt64, owner: Address?)
63
+ access(all) view fun emitNFTUpdated(_ nftRef: auth(Update) &{NonFungibleToken.NFT})
69
64
  {
70
- emit Updated(id: nftRef.getID(), uuid: nftRef.uuid, owner: nftRef.owner?.address, type: nftRef.getType().identifier)
65
+ emit Updated(type: nftRef.getType().identifier, id: nftRef.id, uuid: nftRef.uuid, owner: nftRef.owner?.address)
71
66
  }
72
67
 
73
68
 
74
69
  /// Event that is emitted when a token is withdrawn,
75
- /// indicating the owner of the collection that it was withdrawn from.
70
+ /// indicating the type, id, uuid, the owner of the collection that it was withdrawn from,
71
+ /// and the UUID of the resource it was withdrawn from, usually a collection.
76
72
  ///
77
73
  /// If the collection is not in an account's storage, `from` will be `nil`.
78
74
  ///
79
- access(all) event Withdraw(id: UInt64, uuid: UInt64, from: Address?, type: String)
75
+ access(all) event Withdrawn(type: String, id: UInt64, uuid: UInt64, from: Address?, providerUUID: UInt64)
80
76
 
81
77
  /// Event that emitted when a token is deposited to a collection.
78
+ /// Indicates the type, id, uuid, the owner of the collection that it was deposited to,
79
+ /// and the UUID of the collection it was deposited to
82
80
  ///
83
- /// It indicates the owner of the collection that it was deposited to.
81
+ /// If the collection is not in an account's storage, `from`, will be `nil`.
84
82
  ///
85
- access(all) event Deposit(id: UInt64, uuid: UInt64, to: Address?, type: String)
83
+ access(all) event Deposited(type: String, id: UInt64, uuid: UInt64, to: Address?, collectionUUID: UInt64)
86
84
 
87
85
  /// Interface that the NFTs must conform to
88
86
  ///
89
87
  access(all) resource interface NFT: ViewResolver.Resolver {
90
- /// The unique ID that each NFT has
91
- access(all) view fun getID(): UInt64
92
88
 
93
- // access(all) event ResourceDestroyed(uuid: UInt64 = self.uuid, type: self.getType().identifier)
89
+ /// unique ID for the NFT
90
+ access(all) let id: UInt64
91
+
92
+ /// Event that is emitted automatically every time a resource is destroyed
93
+ /// The type information is included in the metadata event so it is not needed as an argument
94
+ access(all) event ResourceDestroyed(id: UInt64 = self.id, uuid: UInt64 = self.uuid)
95
+
96
+ /// createEmptyCollection creates an empty Collection that is able to store the NFT
97
+ /// and returns it to the caller so that they can own NFTs
98
+ /// @return A an empty collection that can store this NFT
99
+ access(all) fun createEmptyCollection(): @{Collection} {
100
+ post {
101
+ result.getLength() == 0: "The created collection must be empty!"
102
+ result.isSupportedNFTType(type: self.getType()): "The created collection must support this NFT type"
103
+ }
104
+ }
105
+
106
+ /// Gets all the NFTs that this NFT directly owns
107
+ /// @return A dictionary of all subNFTS keyed by type
108
+ access(all) view fun getAvailableSubNFTS(): {Type: UInt64} {
109
+ return {}
110
+ }
94
111
 
95
112
  /// Get a reference to an NFT that this NFT owns
96
113
  /// Both arguments are optional to allow the NFT to choose
97
114
  /// how it returns sub NFTs depending on what arguments are provided
98
- /// For example, if `type` has a value, but `id` doesn't, the NFT
115
+ /// For example, if `type` has a value, but `id` doesn't, the NFT
99
116
  /// can choose which NFT of that type to return if there is a "default"
100
117
  /// If both are `nil`, then NFTs that only store a single NFT can just return
101
- /// that. This helps callers who aren't sure what they are looking for
118
+ /// that. This helps callers who aren't sure what they are looking for
102
119
  ///
103
120
  /// @param type: The Type of the desired NFT
104
121
  /// @param id: The id of the NFT to borrow
@@ -109,7 +126,7 @@ access(all) contract NonFungibleToken {
109
126
  }
110
127
  }
111
128
 
112
- /// Interface to mediate withdraws from the Collection
129
+ /// Interface to mediate withdrawals from a resource, usually a Collection
113
130
  ///
114
131
  access(all) resource interface Provider {
115
132
 
@@ -118,10 +135,11 @@ access(all) contract NonFungibleToken {
118
135
 
119
136
  /// withdraw removes an NFT from the collection and moves it to the caller
120
137
  /// It does not specify whether the ID is UUID or not
121
- access(Withdrawable) fun withdraw(withdrawID: UInt64): @{NFT} {
138
+ /// @param withdrawID: The id of the NFT to withdraw from the collection
139
+ access(Withdraw) fun withdraw(withdrawID: UInt64): @{NFT} {
122
140
  post {
123
- result.getID() == withdrawID: "The ID of the withdrawn token must be the same as the requested ID"
124
- emit Withdraw(id: result.getID(), uuid: result.uuid, from: self.owner?.address, type: result.getType().identifier)
141
+ result.id == withdrawID: "The ID of the withdrawn token must be the same as the requested ID"
142
+ emit Withdrawn(type: result.getType().identifier, id: result.id, uuid: result.uuid, from: self.owner?.address, providerUUID: self.uuid)
125
143
  }
126
144
  }
127
145
  }
@@ -131,61 +149,93 @@ access(all) contract NonFungibleToken {
131
149
  access(all) resource interface Receiver {
132
150
 
133
151
  /// deposit takes an NFT as an argument and adds it to the Collection
134
- ///
152
+ /// @param token: The NFT to deposit
135
153
  access(all) fun deposit(token: @{NFT})
136
154
 
137
155
  /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
156
+ /// @return A dictionary of types mapped to booleans indicating if this
157
+ /// reciever supports it
138
158
  access(all) view fun getSupportedNFTTypes(): {Type: Bool}
139
159
 
140
160
  /// Returns whether or not the given type is accepted by the collection
141
161
  /// A collection that can accept any type should just return true by default
162
+ /// @param type: An NFT type
163
+ /// @return A boolean indicating if this receiver can recieve the desired NFT type
142
164
  access(all) view fun isSupportedNFTType(type: Type): Bool
143
165
  }
144
166
 
167
+ /// Kept for backwards-compatibility reasons
168
+ access(all) resource interface CollectionPublic {
169
+ access(all) fun deposit(token: @{NFT})
170
+ access(all) view fun getLength(): Int
171
+ access(all) view fun getIDs(): [UInt64]
172
+ access(all) fun forEachID(_ f: fun (UInt64): Bool): Void
173
+ access(all) view fun borrowNFT(_ id: UInt64): &{NFT}?
174
+ }
175
+
145
176
  /// Requirement for the concrete resource type
146
177
  /// to be declared in the implementing contract
147
178
  ///
148
- access(all) resource interface Collection: Provider, Receiver, ViewResolver.ResolverCollection {
149
-
150
- /// Return the default storage path for the collection
151
- access(all) view fun getDefaultStoragePath(): StoragePath?
152
-
153
- /// Return the default public path for the collection
154
- access(all) view fun getDefaultPublicPath(): PublicPath?
179
+ access(all) resource interface Collection: Provider, Receiver, CollectionPublic, ViewResolver.ResolverCollection {
155
180
 
156
- /// Normally we would require that the collection specify
157
- /// a specific dictionary to store the NFTs, but this isn't necessary any more
158
- /// as long as all the other functions are there
181
+ access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
159
182
 
160
- /// createEmptyCollection creates an empty Collection
161
- /// and returns it to the caller so that they can own NFTs
162
- access(all) fun createEmptyCollection(): @{Collection} {
163
- post {
164
- result.getLength() == 0: "The created collection must be empty!"
165
- }
166
- }
167
-
168
- /// deposit takes a NFT and adds it to the collections dictionary
169
- /// and adds the ID to the id array
183
+ /// deposit takes a NFT as an argument and stores it in the collection
184
+ /// @param token: The NFT to deposit into the collection
170
185
  access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
171
186
  pre {
172
187
  // We emit the deposit event in the `Collection` interface
173
188
  // because the `Collection` interface is almost always the final destination
174
189
  // of tokens and deposit emissions from custom receivers could be confusing
175
190
  // and hard to reconcile to event listeners
176
- emit Deposit(id: token.getID(), uuid: token.uuid, to: self.owner?.address, type: token.getType().identifier)
191
+ emit Deposited(type: token.getType().identifier, id: token.id, uuid: token.uuid, to: self.owner?.address, collectionUUID: self.uuid)
177
192
  }
178
193
  }
179
194
 
180
195
  /// Gets the amount of NFTs stored in the collection
181
- access(all) view fun getLength(): Int
196
+ /// @return An integer indicating the size of the collection
197
+ access(all) view fun getLength(): Int {
198
+ return self.ownedNFTs.length
199
+ }
182
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
+ }
207
+
208
+ /// Borrows a reference to an NFT stored in the collection
209
+ /// If the NFT with the specified ID is not in the collection,
210
+ /// the function should return `nil` and not panic.
211
+ ///
212
+ /// @param id: The desired nft id in the collection to return a referece for.
213
+ /// @return An optional reference to the NFT
183
214
  access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
184
215
  post {
185
- (result == nil) || (result?.getID() == id):
216
+ (result == nil) || (result?.id == id):
186
217
  "Cannot borrow NFT reference: The ID of the returned reference does not match the ID that was specified"
187
218
  }
188
- return nil
219
+ }
220
+
221
+ /// createEmptyCollection creates an empty Collection of the same type
222
+ /// and returns it to the caller
223
+ /// @return A an empty collection of the same type
224
+ access(all) fun createEmptyCollection(): @{Collection} {
225
+ post {
226
+ result.getType() == self.getType(): "The created collection does not have the same type as this collection"
227
+ result.getLength() == 0: "The created collection must be empty!"
228
+ }
229
+ }
230
+ }
231
+
232
+ /// createEmptyCollection creates an empty Collection for the specified NFT type
233
+ /// and returns it to the caller so that they can own NFTs
234
+ /// @param nftType: The desired nft type to return a collection for.
235
+ /// @return An array of NFT Types that the implementing contract defines.
236
+ access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
237
+ post {
238
+ result.getIDs().length == 0: "The created collection must be empty!"
189
239
  }
190
240
  }
191
- }
241
+ }
@@ -16,29 +16,37 @@ their tokens to.
16
16
 
17
17
  import "FungibleToken"
18
18
 
19
- pub contract TokenForwarding {
19
+ access(all) contract TokenForwarding {
20
20
 
21
21
  // Event that is emitted when tokens are deposited to the target receiver
22
- pub event ForwardedDeposit(amount: UFix64, from: Address?)
22
+ access(all) event ForwardedDeposit(amount: UFix64, from: Address?)
23
23
 
24
- pub resource interface ForwarderPublic {
25
- pub fun check(): Bool
26
- pub fun safeBorrow(): &{FungibleToken.Receiver}?
24
+ access(all) resource interface ForwarderPublic {
25
+ access(all) fun check(): Bool
26
+ access(all) fun safeBorrow(): &{FungibleToken.Receiver}?
27
27
  }
28
28
 
29
- pub resource Forwarder: FungibleToken.Receiver, ForwarderPublic {
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
- pub fun deposit(from: @FungibleToken.Vault) {
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
- pub fun check(): Bool {
59
+ access(all) fun check(): Bool {
52
60
  return self.recipient.check<&{FungibleToken.Receiver}>()
53
61
  }
54
62
 
55
- pub fun safeBorrow(): &{FungibleToken.Receiver}? {
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
- pub fun changeRecipient(_ newRecipient: Capability) {
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
- pub fun createNewForwarder(recipient: Capability): @Forwarder {
86
+ access(all) fun createNewForwarder(recipient: Capability): @Forwarder {
79
87
  return <-create Forwarder(recipient: recipient)
80
88
  }
81
89
  }
@@ -1,43 +1,47 @@
1
- // Taken from the NFT Metadata standard, this contract exposes an interface to let
1
+ // Taken from the NFT Metadata standard, this contract exposes an interface to let
2
2
  // anyone borrow a contract and resolve views on it.
3
3
  //
4
4
  // This will allow you to obtain information about a contract without necessarily knowing anything about it.
5
5
  // All you need is its address and name and you're good to go!
6
6
  access(all) contract interface ViewResolver {
7
7
 
8
- /// Function that returns all the Metadata Views implemented by the resolving contract
8
+ /// Function that returns all the Metadata Views implemented by the resolving contract.
9
+ /// Some contracts may have multiple resource types that support metadata views
10
+ /// so there there is an optional parameter for specify which resource type the caller
11
+ /// is looking for views for.
12
+ /// Some contract-level views may be type-agnostic. In that case, the contract
13
+ /// should return the same views regardless of what type is passed in.
9
14
  ///
15
+ /// @param resourceType: An optional resource type to return views for
10
16
  /// @return An array of Types defining the implemented views. This value will be used by
11
17
  /// developers to know which parameter to pass to the resolveView() method.
12
18
  ///
13
- access(all) view fun getViews(): [Type] {
14
- return []
15
- }
19
+ access(all) view fun getContractViews(resourceType: Type?): [Type]
16
20
 
17
21
  /// Function that resolves a metadata view for this token.
22
+ /// Some contracts may have multiple resource types that support metadata views
23
+ /// so there there is an optional parameter for specify which resource type the caller
24
+ /// is looking for views for.
25
+ /// Some contract-level views may be type-agnostic. In that case, the contract
26
+ /// should return the same views regardless of what type is passed in.
18
27
  ///
28
+ /// @param resourceType: An optional resource type to return views for
19
29
  /// @param view: The Type of the desired view.
20
30
  /// @return A structure representing the requested view.
21
31
  ///
22
- access(all) fun resolveView(_ view: Type): AnyStruct? {
23
- return nil
24
- }
32
+ access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct?
25
33
 
26
- /// Provides access to a set of metadata views. A struct or
27
- /// resource (e.g. an NFT) can implement this interface to provide access to
34
+ /// Provides access to a set of metadata views. A struct or
35
+ /// resource (e.g. an NFT) can implement this interface to provide access to
28
36
  /// the views that it supports.
29
37
  ///
30
38
  access(all) resource interface Resolver {
31
39
 
32
40
  /// Same as getViews above, but on a specific NFT instead of a contract
33
- access(all) view fun getViews(): [Type] {
34
- return []
35
- }
41
+ access(all) view fun getViews(): [Type]
36
42
 
37
43
  /// Same as resolveView above, but on a specific NFT instead of a contract
38
- access(all) fun resolveView(_ view: Type): AnyStruct? {
39
- return nil
40
- }
44
+ access(all) fun resolveView(_ view: Type): AnyStruct?
41
45
  }
42
46
 
43
47
  /// A group of view resolvers indexed by ID.