@flowtyio/flow-contracts 0.0.18 → 0.1.0-beta.2
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/contracts/FlowStorageFees.cdc +49 -51
- package/contracts/FlowToken.cdc +90 -53
- package/contracts/FungibleToken.cdc +91 -127
- package/contracts/FungibleTokenMetadataViews.cdc +52 -43
- package/contracts/MetadataViews.cdc +345 -363
- package/contracts/NonFungibleToken.cdc +93 -104
- package/contracts/ViewResolver.cdc +34 -5
- package/contracts/lost-and-found/FeeEstimator.cdc +14 -22
- package/contracts/lost-and-found/LostAndFound.cdc +185 -177
- package/contracts/lost-and-found/LostAndFoundHelper.cdc +12 -12
- package/package.json +1 -1
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
## `NonFungibleToken` contract interface
|
|
6
6
|
|
|
7
|
-
The interface that all Non-Fungible Token contracts
|
|
7
|
+
The interface that all Non-Fungible Token contracts should conform to.
|
|
8
8
|
If a user wants to deploy a new NFT contract, their contract would need
|
|
9
9
|
to implement the NonFungibleToken interface.
|
|
10
10
|
|
|
11
|
-
Their contract
|
|
11
|
+
Their contract must follow all the rules and naming
|
|
12
12
|
that the interface specifies.
|
|
13
13
|
|
|
14
14
|
## `NFT` resource
|
|
@@ -41,162 +41,151 @@ Collection to complete the transfer.
|
|
|
41
41
|
|
|
42
42
|
*/
|
|
43
43
|
|
|
44
|
+
import "ViewResolver"
|
|
45
|
+
|
|
44
46
|
/// The main NFT contract interface. Other NFT contracts will
|
|
45
47
|
/// import and implement this interface
|
|
46
48
|
///
|
|
47
|
-
|
|
49
|
+
access(all) contract NonFungibleToken {
|
|
50
|
+
|
|
51
|
+
/// An entitlement for allowing the withdrawal of tokens from a Vault
|
|
52
|
+
access(all) entitlement Withdrawable
|
|
48
53
|
|
|
49
|
-
///
|
|
50
|
-
|
|
54
|
+
/// An entitlement for allowing updates and update events for an NFT
|
|
55
|
+
access(all) entitlement Updatable
|
|
51
56
|
|
|
52
|
-
/// Event that
|
|
57
|
+
/// Event that contracts should emit when the metadata of an NFT is updated
|
|
58
|
+
/// It can only be emitted by calling the `emitNFTUpdated` function
|
|
59
|
+
/// with an `Updatable` entitled reference to the NFT that was updated
|
|
60
|
+
/// The entitlement prevents spammers from calling this from other users' collections
|
|
61
|
+
/// because only code within a collection or that has special entitled access
|
|
62
|
+
/// to the collections methods will be able to get the entitled reference
|
|
63
|
+
///
|
|
64
|
+
/// The event makes it so that third-party indexers can monitor the events
|
|
65
|
+
/// and query the updated metadata from the owners' collections.
|
|
53
66
|
///
|
|
54
|
-
|
|
67
|
+
access(all) event Updated(id: UInt64, uuid: UInt64, owner: Address?, type: String)
|
|
68
|
+
access(all) view fun emitNFTUpdated(_ nftRef: auth(Updatable) &{NonFungibleToken.NFT})
|
|
69
|
+
{
|
|
70
|
+
emit Updated(id: nftRef.getID(), uuid: nftRef.uuid, owner: nftRef.owner?.address, type: nftRef.getType().identifier)
|
|
71
|
+
}
|
|
72
|
+
|
|
55
73
|
|
|
56
74
|
/// Event that is emitted when a token is withdrawn,
|
|
57
75
|
/// indicating the owner of the collection that it was withdrawn from.
|
|
58
76
|
///
|
|
59
77
|
/// If the collection is not in an account's storage, `from` will be `nil`.
|
|
60
78
|
///
|
|
61
|
-
|
|
79
|
+
access(all) event Withdraw(id: UInt64, uuid: UInt64, from: Address?, type: String)
|
|
62
80
|
|
|
63
81
|
/// Event that emitted when a token is deposited to a collection.
|
|
64
82
|
///
|
|
65
83
|
/// It indicates the owner of the collection that it was deposited to.
|
|
66
84
|
///
|
|
67
|
-
|
|
85
|
+
access(all) event Deposit(id: UInt64, uuid: UInt64, to: Address?, type: String)
|
|
68
86
|
|
|
69
|
-
/// Interface that the NFTs
|
|
70
|
-
/// The metadata views methods are included here temporarily
|
|
71
|
-
/// because enforcing the metadata interfaces in the standard
|
|
72
|
-
/// would break many contracts in an upgrade. Those breaking changes
|
|
73
|
-
/// are being saved for the stable cadence milestone
|
|
87
|
+
/// Interface that the NFTs must conform to
|
|
74
88
|
///
|
|
75
|
-
|
|
89
|
+
access(all) resource interface NFT: ViewResolver.Resolver {
|
|
76
90
|
/// The unique ID that each NFT has
|
|
77
|
-
|
|
91
|
+
access(all) view fun getID(): UInt64
|
|
78
92
|
|
|
79
|
-
|
|
80
|
-
///
|
|
81
|
-
/// @return An array of Types defining the implemented views. This value will be used by
|
|
82
|
-
/// developers to know which parameter to pass to the resolveView() method.
|
|
83
|
-
///
|
|
84
|
-
pub fun getViews(): [Type] {
|
|
85
|
-
return []
|
|
86
|
-
}
|
|
93
|
+
// access(all) event ResourceDestroyed(uuid: UInt64 = self.uuid, type: self.getType().identifier)
|
|
87
94
|
|
|
88
|
-
///
|
|
95
|
+
/// Get a reference to an NFT that this NFT owns
|
|
96
|
+
/// Both arguments are optional to allow the NFT to choose
|
|
97
|
+
/// 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
|
|
99
|
+
/// can choose which NFT of that type to return if there is a "default"
|
|
100
|
+
/// 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
|
|
89
102
|
///
|
|
90
|
-
/// @param
|
|
91
|
-
/// @
|
|
103
|
+
/// @param type: The Type of the desired NFT
|
|
104
|
+
/// @param id: The id of the NFT to borrow
|
|
92
105
|
///
|
|
93
|
-
|
|
106
|
+
/// @return A structure representing the requested view.
|
|
107
|
+
access(all) fun getSubNFT(type: Type, id: UInt64) : &{NonFungibleToken.NFT}? {
|
|
94
108
|
return nil
|
|
95
109
|
}
|
|
96
110
|
}
|
|
97
111
|
|
|
98
|
-
/// Requirement that all conforming NFT smart contracts have
|
|
99
|
-
/// to define a resource called NFT that conforms to INFT
|
|
100
|
-
///
|
|
101
|
-
pub resource NFT: INFT {
|
|
102
|
-
pub let id: UInt64
|
|
103
|
-
}
|
|
104
|
-
|
|
105
112
|
/// Interface to mediate withdraws from the Collection
|
|
106
113
|
///
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
///
|
|
113
|
-
|
|
114
|
+
access(all) resource interface Provider {
|
|
115
|
+
|
|
116
|
+
// We emit withdraw events from the provider interface because conficting withdraw
|
|
117
|
+
// events aren't as confusing to event listeners as conflicting deposit events
|
|
118
|
+
|
|
119
|
+
/// withdraw removes an NFT from the collection and moves it to the caller
|
|
120
|
+
/// It does not specify whether the ID is UUID or not
|
|
121
|
+
access(Withdrawable) fun withdraw(withdrawID: UInt64): @{NFT} {
|
|
114
122
|
post {
|
|
115
|
-
result.
|
|
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)
|
|
116
125
|
}
|
|
117
126
|
}
|
|
118
127
|
}
|
|
119
128
|
|
|
120
129
|
/// Interface to mediate deposits to the Collection
|
|
121
130
|
///
|
|
122
|
-
|
|
131
|
+
access(all) resource interface Receiver {
|
|
123
132
|
|
|
124
|
-
///
|
|
133
|
+
/// deposit takes an NFT as an argument and adds it to the Collection
|
|
125
134
|
///
|
|
126
|
-
|
|
127
|
-
///
|
|
128
|
-
pub fun deposit(token: @NFT)
|
|
129
|
-
}
|
|
135
|
+
access(all) fun deposit(token: @{NFT})
|
|
130
136
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
pub fun borrowNFT(id: UInt64): &NFT
|
|
138
|
-
/// Safe way to borrow a reference to an NFT that does not panic
|
|
139
|
-
///
|
|
140
|
-
/// @param id: The ID of the NFT that want to be borrowed
|
|
141
|
-
/// @return An optional reference to the desired NFT, will be nil if the passed id does not exist
|
|
142
|
-
///
|
|
143
|
-
pub fun borrowNFTSafe(id: UInt64): &NFT? {
|
|
144
|
-
post {
|
|
145
|
-
result == nil || result!.id == id: "The returned reference's ID does not match the requested ID"
|
|
146
|
-
}
|
|
147
|
-
return nil
|
|
148
|
-
}
|
|
137
|
+
/// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
|
|
138
|
+
access(all) view fun getSupportedNFTTypes(): {Type: Bool}
|
|
139
|
+
|
|
140
|
+
/// Returns whether or not the given type is accepted by the collection
|
|
141
|
+
/// A collection that can accept any type should just return true by default
|
|
142
|
+
access(all) view fun isSupportedNFTType(type: Type): Bool
|
|
149
143
|
}
|
|
150
144
|
|
|
151
145
|
/// Requirement for the concrete resource type
|
|
152
146
|
/// to be declared in the implementing contract
|
|
153
147
|
///
|
|
154
|
-
|
|
148
|
+
access(all) resource interface Collection: Provider, Receiver, ViewResolver.ResolverCollection {
|
|
155
149
|
|
|
156
|
-
///
|
|
157
|
-
|
|
150
|
+
/// Return the default storage path for the collection
|
|
151
|
+
access(all) view fun getDefaultStoragePath(): StoragePath?
|
|
158
152
|
|
|
159
|
-
///
|
|
160
|
-
|
|
161
|
-
/// @param withdrawID: The ID of the NFT that will be withdrawn
|
|
162
|
-
/// @return The resource containing the desired NFT
|
|
163
|
-
///
|
|
164
|
-
pub fun withdraw(withdrawID: UInt64): @NFT
|
|
153
|
+
/// Return the default public path for the collection
|
|
154
|
+
access(all) view fun getDefaultPublicPath(): PublicPath?
|
|
165
155
|
|
|
166
|
-
///
|
|
167
|
-
///
|
|
168
|
-
///
|
|
169
|
-
/// @param token: An NFT resource
|
|
170
|
-
///
|
|
171
|
-
pub fun deposit(token: @NFT)
|
|
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
|
|
172
159
|
|
|
173
|
-
///
|
|
174
|
-
///
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
+
}
|
|
178
167
|
|
|
179
|
-
///
|
|
180
|
-
///
|
|
181
|
-
|
|
182
|
-
/// @param id: The ID of the NFT that want to be borrowed
|
|
183
|
-
/// @return A reference to the NFT
|
|
184
|
-
///
|
|
185
|
-
pub fun borrowNFT(id: UInt64): &NFT {
|
|
168
|
+
/// deposit takes a NFT and adds it to the collections dictionary
|
|
169
|
+
/// and adds the ID to the id array
|
|
170
|
+
access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
|
|
186
171
|
pre {
|
|
187
|
-
|
|
172
|
+
// We emit the deposit event in the `Collection` interface
|
|
173
|
+
// because the `Collection` interface is almost always the final destination
|
|
174
|
+
// of tokens and deposit emissions from custom receivers could be confusing
|
|
175
|
+
// and hard to reconcile to event listeners
|
|
176
|
+
emit Deposit(id: token.getID(), uuid: token.uuid, to: self.owner?.address, type: token.getType().identifier)
|
|
188
177
|
}
|
|
189
178
|
}
|
|
190
|
-
}
|
|
191
179
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
180
|
+
/// Gets the amount of NFTs stored in the collection
|
|
181
|
+
access(all) view fun getLength(): Int
|
|
182
|
+
|
|
183
|
+
access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
|
|
184
|
+
post {
|
|
185
|
+
(result == nil) || (result?.getID() == id):
|
|
186
|
+
"Cannot borrow NFT reference: The ID of the returned reference does not match the ID that was specified"
|
|
187
|
+
}
|
|
188
|
+
return nil
|
|
199
189
|
}
|
|
200
190
|
}
|
|
201
191
|
}
|
|
202
|
-
|
|
@@ -1,15 +1,16 @@
|
|
|
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
9
|
///
|
|
9
10
|
/// @return An array of Types defining the implemented views. This value will be used by
|
|
10
11
|
/// developers to know which parameter to pass to the resolveView() method.
|
|
11
12
|
///
|
|
12
|
-
|
|
13
|
+
access(all) view fun getViews(): [Type] {
|
|
13
14
|
return []
|
|
14
15
|
}
|
|
15
16
|
|
|
@@ -18,8 +19,36 @@ pub contract interface ViewResolver {
|
|
|
18
19
|
/// @param view: The Type of the desired view.
|
|
19
20
|
/// @return A structure representing the requested view.
|
|
20
21
|
///
|
|
21
|
-
|
|
22
|
+
access(all) fun resolveView(_ view: Type): AnyStruct? {
|
|
22
23
|
return nil
|
|
23
24
|
}
|
|
25
|
+
|
|
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
|
|
28
|
+
/// the views that it supports.
|
|
29
|
+
///
|
|
30
|
+
access(all) resource interface Resolver {
|
|
31
|
+
|
|
32
|
+
/// Same as getViews above, but on a specific NFT instead of a contract
|
|
33
|
+
access(all) view fun getViews(): [Type] {
|
|
34
|
+
return []
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// 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
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/// A group of view resolvers indexed by ID.
|
|
44
|
+
///
|
|
45
|
+
access(all) resource interface ResolverCollection {
|
|
46
|
+
access(all) view fun borrowViewResolver(id: UInt64): &{Resolver}? {
|
|
47
|
+
return nil
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
access(all) view fun getIDs(): [UInt64] {
|
|
51
|
+
return []
|
|
52
|
+
}
|
|
53
|
+
}
|
|
24
54
|
}
|
|
25
|
-
|
|
@@ -11,49 +11,41 @@ import "FlowToken"
|
|
|
11
11
|
|
|
12
12
|
Consumers of this contract would then need to pop the resource out of the DepositEstimate resource to get it back
|
|
13
13
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
access(all) contract FeeEstimator {
|
|
15
|
+
access(all) resource DepositEstimate {
|
|
16
|
+
access(all) var item: @AnyResource?
|
|
17
|
+
access(all) var storageFee: UFix64
|
|
18
18
|
|
|
19
19
|
init(item: @AnyResource, storageFee: UFix64) {
|
|
20
20
|
self.item <- item
|
|
21
21
|
self.storageFee = storageFee
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
let
|
|
26
|
-
return <-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
destroy() {
|
|
30
|
-
pre {
|
|
31
|
-
self.item == nil: "cannot destroy with non-null item"
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
destroy self.item
|
|
24
|
+
access(all) fun withdraw(): @AnyResource {
|
|
25
|
+
let r <- self.item <- nil
|
|
26
|
+
return <-r!
|
|
35
27
|
}
|
|
36
28
|
}
|
|
37
29
|
|
|
38
|
-
|
|
30
|
+
access(all) fun hasStorageCapacity(_ addr: Address, _ storageFee: UFix64): Bool {
|
|
39
31
|
return FlowStorageFees.defaultTokenAvailableBalance(addr) > storageFee
|
|
40
32
|
}
|
|
41
33
|
|
|
42
|
-
|
|
34
|
+
access(all) fun estimateDeposit(
|
|
43
35
|
item: @AnyResource,
|
|
44
36
|
): @DepositEstimate {
|
|
45
|
-
let storageUsedBefore = FeeEstimator.account.
|
|
46
|
-
FeeEstimator.account.save(<-item, to: /storage/temp)
|
|
47
|
-
let storageUsedAfter = FeeEstimator.account.
|
|
37
|
+
let storageUsedBefore = FeeEstimator.account.storage.used
|
|
38
|
+
FeeEstimator.account.storage.save(<-item, to: /storage/temp)
|
|
39
|
+
let storageUsedAfter = FeeEstimator.account.storage.used
|
|
48
40
|
|
|
49
41
|
let storageDiff = storageUsedAfter - storageUsedBefore
|
|
50
42
|
let storageFee = FeeEstimator.storageUsedToFlowAmount(storageDiff)
|
|
51
|
-
let loadedItem <- FeeEstimator.account.load<@AnyResource>(from: /storage/temp)!
|
|
43
|
+
let loadedItem <- FeeEstimator.account.storage.load<@AnyResource>(from: /storage/temp)!
|
|
52
44
|
let estimate <- create DepositEstimate(item: <-loadedItem, storageFee: storageFee)
|
|
53
45
|
return <- estimate
|
|
54
46
|
}
|
|
55
47
|
|
|
56
|
-
|
|
48
|
+
access(all) fun storageUsedToFlowAmount(_ storageUsed: UInt64): UFix64 {
|
|
57
49
|
let storageMB = FlowStorageFees.convertUInt64StorageBytesToUFix64Megabytes(storageUsed)
|
|
58
50
|
return FlowStorageFees.storageCapacityToFlow(storageMB)
|
|
59
51
|
}
|