Smart Contract
GeniesShardedCollection
A.12450e4bb3b7666e.GeniesShardedCollection
1/*
2 Description: Central Collection for a large number of Genies NFTs
3
4 Adapted from: TopShotShardedCollection.cdc
5 Authors: Joshua Hannan joshua.hannan@dapperlabs.com
6 Bastian Muller bastian@dapperlabs.com
7
8 [...]
9
10 When Cadence is updated to allow larger dictionaries,
11 then this contract can be retired.
12*/
13
14import NonFungibleToken from 0x1d7e57aa55817448
15import Genies from 0x12450e4bb3b7666e
16
17pub contract GeniesShardedCollection {
18 // Named Paths
19 //
20 pub let CollectionStoragePath: StoragePath
21
22 // ShardedCollection stores a dictionary of Genies Collections
23 // A Genies NFT is stored in the field that corresponds to its id % numBuckets
24 pub resource ShardedCollection:
25 Genies.GeniesNFTCollectionPublic,
26 NonFungibleToken.Provider,
27 NonFungibleToken.Receiver,
28 NonFungibleToken.CollectionPublic
29 {
30 // Dictionary of Genies collections
31 pub var collections: @{UInt64: Genies.Collection}
32
33 // The number of buckets to split Genies NFTs into
34 // This makes storage more efficient and performant
35 pub let numBuckets: UInt64
36
37 init(numBuckets: UInt64) {
38 self.collections <- {}
39 self.numBuckets = numBuckets
40
41 // Create a new empty collection for each bucket
42 var i: UInt64 = 0
43 while i < numBuckets {
44
45 self.collections[i] <-! Genies.createEmptyCollection() as! @Genies.Collection
46
47 i = i + (1 as UInt64)
48 }
49 }
50
51 // withdraw removes a Genies NFT from one of the Collections
52 // and moves it to the caller
53 pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT {
54 post {
55 result.id == withdrawID: "The ID of the withdrawn NFT is incorrect"
56 }
57 // Find the bucket it should be withdrawn from
58 let bucket = withdrawID % self.numBuckets
59
60 // Withdraw the Genies NFT
61 let token <- self.collections[bucket]?.withdraw(withdrawID: withdrawID)!
62
63 return <-token
64 }
65
66 // batchWithdraw withdraws multiple tokens and returns them as a Collection
67 //
68 // Parameters: ids: an array of the IDs to be withdrawn from the Collection
69 //
70 // Returns: @NonFungibleToken.Collection a Collection containing the Genies NFTs
71 // that were withdrawn
72 pub fun batchWithdraw(ids: [UInt64]): @NonFungibleToken.Collection {
73 var batchCollection <- Genies.createEmptyCollection()
74
75 // Iterate through the ids and withdraw them from the Collection
76 for id in ids {
77 batchCollection.deposit(token: <-self.withdraw(withdrawID: id))
78 }
79 return <-batchCollection
80 }
81
82 // deposit takes a Genies NFT and adds it to the Collections dictionary
83 pub fun deposit(token: @NonFungibleToken.NFT) {
84
85 // Find the bucket this corresponds to
86 let bucket = token.id % self.numBuckets
87
88 // Remove the collection
89 let collection <- self.collections.remove(key: bucket)!
90
91 // Deposit the nft into the bucket
92 collection.deposit(token: <-token)
93
94 // Put the Collection back in storage
95 self.collections[bucket] <-! collection
96 }
97
98 // batchDeposit takes a Collection object as an argument
99 // and deposits each contained NFT into this Collection
100 pub fun batchDeposit(tokens: @NonFungibleToken.Collection) {
101 let keys = tokens.getIDs()
102
103 // Iterate through the keys in the Collection and deposit each one
104 for key in keys {
105 self.deposit(token: <-tokens.withdraw(withdrawID: key))
106 }
107 destroy tokens
108 }
109
110 // getIDs returns an array of the IDs that are in the Collection
111 pub fun getIDs(): [UInt64] {
112
113 var ids: [UInt64] = []
114 // Concatenate IDs in all the Collections
115 for key in self.collections.keys {
116 for id in self.collections[key]?.getIDs() ?? [] {
117 ids.append(id)
118 }
119 }
120 return ids
121 }
122
123 // borrowNFT Returns a borrowed reference to a Genies NFT in the Collection
124 // so that the caller can read data and call methods from it
125 pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT {
126 post {
127 result.id == id: "The ID of the reference is incorrect"
128 }
129
130 // Get the bucket of the nft to be borrowed
131 let bucket = id % self.numBuckets
132
133 // Find NFT in the collections and borrow a reference
134 return self.collections[bucket]?.borrowNFT(id: id)!
135 }
136
137 // borrowGeniesNFT Returns a borrowed reference to a Genies NFT in the Collection
138 // so that the caller can read data and call methods from it
139 // They can use this to read its setID, playID, serialNumber,
140 // or any of the setData or Play Data associated with it by
141 // getting the setID or playID and reading those fields from
142 // the smart contract
143 //
144 // Parameters: id: The ID of the NFT to get the reference for
145 //
146 // Returns: A reference to the NFT
147 pub fun borrowGeniesNFT(id: UInt64): &Genies.NFT? {
148
149 // Get the bucket of the nft to be borrowed
150 let bucket = id % self.numBuckets
151
152 return self.collections[bucket]?.borrowGeniesNFT(id: id) ?? nil
153 }
154
155 // If a transaction destroys the Collection object,
156 // All the NFTs contained within are also destroyed
157 destroy() {
158 destroy self.collections
159 }
160 }
161
162 // Creates an empty ShardedCollection and returns it to the caller
163 pub fun createEmptyCollection(numBuckets: UInt64): @ShardedCollection {
164 return <-create ShardedCollection(numBuckets: numBuckets)
165 }
166
167 init() {
168 // Set the named paths
169 self.CollectionStoragePath = /storage/GeniesShardedNFTCollection
170 }
171}
172