@flowtyio/flow-contracts 0.1.0-beta.3 → 0.1.0-beta.30
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/Burner.cdc +44 -0
- package/contracts/FlowStorageFees.cdc +15 -15
- package/contracts/FlowToken.cdc +29 -78
- package/contracts/FungibleToken.cdc +80 -53
- package/contracts/FungibleTokenMetadataViews.cdc +13 -25
- package/contracts/FungibleTokenSwitchboard.cdc +360 -0
- package/contracts/MetadataViews.cdc +107 -50
- package/contracts/NonFungibleToken.cdc +110 -60
- package/contracts/TokenForwarding.cdc +19 -11
- package/contracts/ViewResolver.cdc +20 -16
- package/contracts/capability-cache/CapabilityCache.cdc +97 -0
- package/contracts/dapper/DapperUtilityCoin.cdc +106 -39
- package/contracts/dapper/FlowUtilityToken.cdc +107 -40
- 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 +18 -21
- package/contracts/example/ExampleToken.cdc +68 -1
- package/contracts/find/FindViews.cdc +357 -353
- package/contracts/flow-utils/AddressUtils.cdc +20 -23
- package/contracts/flow-utils/ArrayUtils.cdc +10 -11
- package/contracts/flow-utils/ScopedFTProviders.cdc +27 -19
- package/contracts/flow-utils/ScopedNFTProviders.cdc +31 -26
- package/contracts/flow-utils/StringUtils.cdc +24 -37
- 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/contracts/fungible-token-router/FungibleTokenRouter.cdc +105 -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 +29 -25
- package/contracts/nft-catalog/NFTCatalog.cdc +60 -64
- package/contracts/nft-catalog/NFTCatalogAdmin.cdc +28 -27
- package/flow.json +189 -5
- package/package.json +1 -1
- package/contracts/hybrid-custody/factories/NFTProviderAndCollectionPublicFactory.cdc +0 -10
|
@@ -126,15 +126,39 @@ 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
|
|
134
158
|
///
|
|
135
159
|
access(all) let file: {File}
|
|
136
160
|
|
|
137
|
-
/// media-type comes on the form of type/subtype as described here
|
|
161
|
+
/// media-type comes on the form of type/subtype as described here
|
|
138
162
|
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
|
|
139
163
|
///
|
|
140
164
|
access(all) let mediaType: String
|
|
@@ -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>()) {
|
|
@@ -197,7 +221,7 @@ access(all) contract MetadataViews {
|
|
|
197
221
|
}
|
|
198
222
|
|
|
199
223
|
/// View to expose a URL to this item on an external site.
|
|
200
|
-
/// This can be used by applications like .find and Blocto to direct users
|
|
224
|
+
/// This can be used by applications like .find and Blocto to direct users
|
|
201
225
|
/// to the original link for an NFT or a project page that describes the NFT collection.
|
|
202
226
|
/// eg https://www.my-nft-project.com/overview-of-nft-collection
|
|
203
227
|
///
|
|
@@ -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>()) {
|
|
@@ -223,27 +247,27 @@ access(all) contract MetadataViews {
|
|
|
223
247
|
return nil
|
|
224
248
|
}
|
|
225
249
|
|
|
226
|
-
/// View that defines the composable royalty standard that gives marketplaces a
|
|
250
|
+
/// View that defines the composable royalty standard that gives marketplaces a
|
|
227
251
|
/// unified interface to support NFT royalties.
|
|
228
252
|
///
|
|
229
253
|
access(all) struct Royalty {
|
|
230
254
|
|
|
231
255
|
/// Generic FungibleToken Receiver for the beneficiary of the royalty
|
|
232
256
|
/// Can get the concrete type of the receiver with receiver.getType()
|
|
233
|
-
/// Recommendation - Users should create a new link for a FlowToken
|
|
234
|
-
/// receiver for this using `getRoyaltyReceiverPublicPath()`, and not
|
|
235
|
-
/// use the default FlowToken receiver. This will allow users to update
|
|
257
|
+
/// Recommendation - Users should create a new link for a FlowToken
|
|
258
|
+
/// receiver for this using `getRoyaltyReceiverPublicPath()`, and not
|
|
259
|
+
/// use the default FlowToken receiver. This will allow users to update
|
|
236
260
|
/// the capability in the future to use a more generic capability
|
|
237
261
|
access(all) let receiver: Capability<&{FungibleToken.Receiver}>
|
|
238
262
|
|
|
239
|
-
/// Multiplier used to calculate the amount of sale value transferred to
|
|
240
|
-
/// royalty receiver. Note - It should be between 0.0 and 1.0
|
|
241
|
-
/// Ex - If the sale value is x and multiplier is 0.56 then the royalty
|
|
263
|
+
/// Multiplier used to calculate the amount of sale value transferred to
|
|
264
|
+
/// royalty receiver. Note - It should be between 0.0 and 1.0
|
|
265
|
+
/// Ex - If the sale value is x and multiplier is 0.56 then the royalty
|
|
242
266
|
/// value would be 0.56 * x.
|
|
243
267
|
/// Generally percentage get represented in terms of basis points
|
|
244
|
-
/// in solidity based smart contracts while cadence offers `UFix64`
|
|
245
|
-
/// that already supports the basis points use case because its
|
|
246
|
-
/// operations are entirely deterministic integer operations and support
|
|
268
|
+
/// in solidity based smart contracts while cadence offers `UFix64`
|
|
269
|
+
/// that already supports the basis points use case because its
|
|
270
|
+
/// operations are entirely deterministic integer operations and support
|
|
247
271
|
/// up to 8 points of precision.
|
|
248
272
|
access(all) let cut: UFix64
|
|
249
273
|
|
|
@@ -263,7 +287,7 @@ access(all) contract MetadataViews {
|
|
|
263
287
|
}
|
|
264
288
|
|
|
265
289
|
/// Wrapper view for multiple Royalty views.
|
|
266
|
-
/// Marketplaces can query this `Royalties` struct from NFTs
|
|
290
|
+
/// Marketplaces can query this `Royalties` struct from NFTs
|
|
267
291
|
/// and are expected to pay royalties based on these specifications.
|
|
268
292
|
///
|
|
269
293
|
access(all) struct Royalties {
|
|
@@ -353,9 +377,9 @@ access(all) contract MetadataViews {
|
|
|
353
377
|
view init(_ traits: [Trait]) {
|
|
354
378
|
self.traits = traits
|
|
355
379
|
}
|
|
356
|
-
|
|
380
|
+
|
|
357
381
|
/// Adds a single Trait to the Traits view
|
|
358
|
-
///
|
|
382
|
+
///
|
|
359
383
|
/// @param Trait: The trait struct to be added
|
|
360
384
|
///
|
|
361
385
|
access(all) fun addTrait(_ t: Trait) {
|
|
@@ -377,8 +401,8 @@ access(all) contract MetadataViews {
|
|
|
377
401
|
return nil
|
|
378
402
|
}
|
|
379
403
|
|
|
380
|
-
/// Helper function to easily convert a dictionary to traits. For NFT
|
|
381
|
-
/// collections that do not need either of the optional values of a Trait,
|
|
404
|
+
/// Helper function to easily convert a dictionary to traits. For NFT
|
|
405
|
+
/// collections that do not need either of the optional values of a Trait,
|
|
382
406
|
/// this method should suffice to give them an array of valid traits.
|
|
383
407
|
///
|
|
384
408
|
/// @param dict: The dictionary to be converted to Traits
|
|
@@ -494,7 +518,7 @@ access(all) contract MetadataViews {
|
|
|
494
518
|
}
|
|
495
519
|
|
|
496
520
|
/// View to expose rarity information for a single rarity
|
|
497
|
-
/// Note that a rarity needs to have either score or description but it can
|
|
521
|
+
/// Note that a rarity needs to have either score or description but it can
|
|
498
522
|
/// have both
|
|
499
523
|
///
|
|
500
524
|
access(all) struct Rarity {
|
|
@@ -534,8 +558,8 @@ access(all) contract MetadataViews {
|
|
|
534
558
|
return nil
|
|
535
559
|
}
|
|
536
560
|
|
|
537
|
-
/// NFTView wraps all Core views along `id` and `uuid` fields, and is used
|
|
538
|
-
/// to give a complete picture of an NFT. Most NFTs should implement this
|
|
561
|
+
/// NFTView wraps all Core views along `id` and `uuid` fields, and is used
|
|
562
|
+
/// to give a complete picture of an NFT. Most NFTs should implement this
|
|
539
563
|
/// view.
|
|
540
564
|
///
|
|
541
565
|
access(all) struct NFTView {
|
|
@@ -569,7 +593,7 @@ access(all) contract MetadataViews {
|
|
|
569
593
|
}
|
|
570
594
|
}
|
|
571
595
|
|
|
572
|
-
/// Helper to get an NFT view
|
|
596
|
+
/// Helper to get an NFT view
|
|
573
597
|
///
|
|
574
598
|
/// @param id: The NFT id
|
|
575
599
|
/// @param viewResolver: A reference to the resolver resource
|
|
@@ -594,7 +618,7 @@ access(all) contract MetadataViews {
|
|
|
594
618
|
}
|
|
595
619
|
|
|
596
620
|
/// View to expose the information needed store and retrieve an NFT.
|
|
597
|
-
/// This can be used by applications to setup a NFT collection with proper
|
|
621
|
+
/// This can be used by applications to setup a NFT collection with proper
|
|
598
622
|
/// storage and public capabilities.
|
|
599
623
|
///
|
|
600
624
|
access(all) struct NFTCollectionData {
|
|
@@ -605,24 +629,13 @@ access(all) contract MetadataViews {
|
|
|
605
629
|
/// including standard NFT interfaces and metadataviews interfaces
|
|
606
630
|
access(all) let publicPath: PublicPath
|
|
607
631
|
|
|
608
|
-
///
|
|
609
|
-
///
|
|
610
|
-
access(all) let providerPath: PrivatePath
|
|
611
|
-
|
|
612
|
-
/// Public collection type that is expected to provide sufficient read-only access to standard
|
|
613
|
-
/// functions (deposit + getIDs + borrowNFT). For new
|
|
614
|
-
/// collections, this may be set to be equal to the type specified in `publicLinkedType`.
|
|
632
|
+
/// The concrete type of the collection that is exposed to the public
|
|
633
|
+
/// now that entitlements exist, it no longer needs to be restricted to a specific interface
|
|
615
634
|
access(all) let publicCollection: Type
|
|
616
635
|
|
|
617
|
-
/// Type that should be linked at the aforementioned public path
|
|
618
|
-
/// restricted type with many interfaces. Notably the
|
|
619
|
-
/// `NFT.Receiver`, and `ViewResolver.ResolverCollection` interfaces are required.
|
|
636
|
+
/// Type that should be linked at the aforementioned public path
|
|
620
637
|
access(all) let publicLinkedType: Type
|
|
621
638
|
|
|
622
|
-
/// Type that should be linked at the aforementioned private path. This is normally
|
|
623
|
-
/// a restricted type with at a minimum the `NFT.Provider` interface
|
|
624
|
-
access(all) let providerLinkedType: Type
|
|
625
|
-
|
|
626
639
|
/// Function that allows creation of an empty NFT collection that is intended to store
|
|
627
640
|
/// this NFT.
|
|
628
641
|
access(all) let createEmptyCollection: fun(): @{NonFungibleToken.Collection}
|
|
@@ -630,22 +643,17 @@ access(all) contract MetadataViews {
|
|
|
630
643
|
view init(
|
|
631
644
|
storagePath: StoragePath,
|
|
632
645
|
publicPath: PublicPath,
|
|
633
|
-
providerPath: PrivatePath,
|
|
634
646
|
publicCollection: Type,
|
|
635
647
|
publicLinkedType: Type,
|
|
636
|
-
providerLinkedType: Type,
|
|
637
648
|
createEmptyCollectionFunction: fun(): @{NonFungibleToken.Collection}
|
|
638
649
|
) {
|
|
639
650
|
pre {
|
|
640
|
-
publicLinkedType.isSubtype(of: Type<&{NonFungibleToken.
|
|
641
|
-
providerLinkedType.isSubtype(of: Type<&{NonFungibleToken.Provider, ViewResolver.ResolverCollection}>()): "Provider type must include NonFungibleToken.Provider and ViewResolver.ResolverCollection interface."
|
|
651
|
+
publicLinkedType.isSubtype(of: Type<&{NonFungibleToken.Collection}>()): "Public type must be a subtype of NonFungibleToken.Collection interface."
|
|
642
652
|
}
|
|
643
653
|
self.storagePath=storagePath
|
|
644
654
|
self.publicPath=publicPath
|
|
645
|
-
self.providerPath = providerPath
|
|
646
655
|
self.publicCollection=publicCollection
|
|
647
656
|
self.publicLinkedType=publicLinkedType
|
|
648
|
-
self.providerLinkedType = providerLinkedType
|
|
649
657
|
self.createEmptyCollection=createEmptyCollectionFunction
|
|
650
658
|
}
|
|
651
659
|
}
|
|
@@ -665,7 +673,7 @@ access(all) contract MetadataViews {
|
|
|
665
673
|
}
|
|
666
674
|
|
|
667
675
|
/// View to expose the information needed to showcase this NFT's
|
|
668
|
-
/// collection. This can be used by applications to give an overview and
|
|
676
|
+
/// collection. This can be used by applications to give an overview and
|
|
669
677
|
/// graphics of the NFT collection this NFT belongs to.
|
|
670
678
|
///
|
|
671
679
|
access(all) struct NFTCollectionDisplay {
|
|
@@ -681,7 +689,7 @@ access(all) contract MetadataViews {
|
|
|
681
689
|
// Square-sized image to represent this collection.
|
|
682
690
|
access(all) let squareImage: MetadataViews.Media
|
|
683
691
|
|
|
684
|
-
// 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.
|
|
685
693
|
access(all) let bannerImage: MetadataViews.Media
|
|
686
694
|
|
|
687
695
|
// Social links to reach this collection's social homepages.
|
|
@@ -705,7 +713,7 @@ access(all) contract MetadataViews {
|
|
|
705
713
|
}
|
|
706
714
|
}
|
|
707
715
|
|
|
708
|
-
/// Helper to get NFTCollectionDisplay in a way that will return a typed
|
|
716
|
+
/// Helper to get NFTCollectionDisplay in a way that will return a typed
|
|
709
717
|
/// Optional
|
|
710
718
|
///
|
|
711
719
|
/// @param viewResolver: A reference to the resolver resource
|
|
@@ -719,4 +727,53 @@ access(all) contract MetadataViews {
|
|
|
719
727
|
}
|
|
720
728
|
return nil
|
|
721
729
|
}
|
|
722
|
-
|
|
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
|
+
}
|
|
@@ -2,20 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## The Flow Non-Fungible Token standard
|
|
4
4
|
|
|
5
|
-
## `NonFungibleToken` contract
|
|
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
|
|
9
|
-
|
|
8
|
+
If a user wants to deploy a new NFT contract, their contract should implement
|
|
9
|
+
The types defined here
|
|
10
10
|
|
|
11
|
-
|
|
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
|
|
30
|
-
|
|
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
|
|
47
|
-
/// import and implement this
|
|
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
|
|
47
|
+
access(all) entitlement Withdraw
|
|
53
48
|
|
|
54
49
|
/// An entitlement for allowing updates and update events for an NFT
|
|
55
|
-
access(all) entitlement
|
|
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
|
|
68
|
-
access(all) view fun emitNFTUpdated(_ nftRef: auth(
|
|
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(
|
|
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
|
|
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
|
-
///
|
|
81
|
+
/// If the collection is not in an account's storage, `from`, will be `nil`.
|
|
84
82
|
///
|
|
85
|
-
access(all) event
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
124
|
-
emit
|
|
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
|
-
|
|
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
|
-
///
|
|
161
|
-
///
|
|
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
|
|
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
|
-
|
|
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?.
|
|
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
|
-
|
|
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
|
+
}
|