Smart Contract

GeniesShardedCollection

A.12450e4bb3b7666e.GeniesShardedCollection

Deployed

2h ago
Feb 28, 2026, 09:42:44 PM UTC

Dependents

0 imports
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