Smart Contract

CricketMomentsShardedCollection

A.4eded0de73020ca5.CricketMomentsShardedCollection

Deployed

1w ago
Feb 19, 2026, 08:41:48 AM UTC

Dependents

17 imports
1// SPDX-License-Identifier: UNLICENSED
2
3/*
4    Description: Central Collection for a large number of CricketMoments
5                 NFTs
6
7    This contract bundles together a bunch of Collection objects 
8    in a dictionary, and then distributes the individual Moments between them 
9    while implementing the same public interface 
10    as the default CricketMomentCollection implementation. 
11
12    If we assume that Moment IDs are uniformly distributed, 
13    a ShardedCollection with 10 inner Collections should be able 
14    to store 10x as many Moments (or ~1M).
15
16    When Cadence is updated to allow larger dictionaries, 
17    then this contract can be retired.
18
19*/
20import NonFungibleToken from 0x1d7e57aa55817448
21import CricketMoments from 0x4eded0de73020ca5
22
23access(all) contract CricketMomentsShardedCollection {
24
25    access(all) let ShardedCollectionStoragePath: StoragePath
26
27    // ShardedCollection stores a dictionary of CricketMoments Collections
28    // A Moment is stored in the field that corresponds to its id % numBuckets
29    access(all) resource ShardedCollection: CricketMoments.CricketMomentsCollectionPublic, NonFungibleToken.CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver { 
30        
31        // Dictionary of CricketMoments collections
32        access(all) var collections: @{UInt64: CricketMoments.Collection}
33
34        access(all) fun forEachID(_ f: fun (UInt64): Bool): Void {
35            for key in self.collections.keys {
36                 let col = &self.collections[key] as &CricketMoments.Collection?
37                 col?.forEachID(f)
38            }
39        }
40
41        // The number of buckets to split Moments into
42        // This makes storage more efficient and performant
43        access(all) let numBuckets: UInt64
44
45        init(numBuckets: UInt64) {
46            self.collections <- {}
47            self.numBuckets = numBuckets
48
49            // Create a new empty collection for each bucket
50            var i: UInt64 = 0
51            while i < numBuckets {
52
53                self.collections[i] <-! CricketMoments.createEmptyCollection(nftType: Type<@CricketMoments.NFT>()) as! @CricketMoments.Collection
54
55                i = i + 1 as UInt64
56            }
57        }
58
59        // withdraw removes a Moment from one of the Collections 
60        // and moves it to the caller
61        access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
62            post {
63                result.id == withdrawID: "The ID of the withdrawn NFT is incorrect"
64            }
65            // Find the bucket it should be withdrawn from
66            let bucket = withdrawID % self.numBuckets
67
68            // Withdraw the moment
69            let token <- self.collections[bucket]?.withdraw(withdrawID: withdrawID)!
70            
71            return <-token
72        }
73
74        // deposit takes a Moment and adds it to the Collections dictionary
75        access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
76
77            // Find the bucket this corresponds to
78            let bucket = token.id % self.numBuckets
79
80            // Get collection Reference
81            let collectionRef = (&self.collections[bucket] as &CricketMoments.Collection?)!
82
83            // Deposit the nft into the bucket
84            collectionRef.deposit(token: <-token)
85
86        }
87
88        // getIDs returns an array of the IDs that are in the Collection
89        access(all) view fun getIDs(): [UInt64] {
90
91            var ids: [UInt64] = []
92            // Concatenate IDs in all the Collections
93            for key in self.collections.keys {
94                let collectionIDs = self.collections[key]?.getIDs() ?? []
95                ids = ids.concat(collectionIDs)
96            }
97            return ids
98        }
99
100        // borrowNFT Returns a borrowed reference to a Moment in the Collection
101        // so that the caller can read data and call methods from it
102        access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
103            post {
104                result?.id == id: "The ID of the reference is incorrect"
105            }
106
107            // Get the bucket of the nft to be borrowed
108            let bucket = id % self.numBuckets
109
110            // Find NFT in the collections and borrow a reference
111            return self.collections[bucket]?.borrowNFT(id)!
112        }
113
114
115        // borrowCricketMoment Returns a borrowed reference to a Moment in the Collection
116        // so that the caller can read data and call methods from it
117        // They can use this to read its serial, momentId, metadata
118        //
119        // Parameters: id: The ID of the NFT to get the reference for
120        //
121        // Returns: A reference to the NFT
122        access(all) view fun borrowCricketMoment(id: UInt64): &CricketMoments.NFT? {
123
124            // Get the bucket of the nft to be borrowed
125            let bucket = id % self.numBuckets
126
127            return self.collections[bucket]?.borrowCricketMoment(id: id) ?? nil
128        }
129
130        /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
131        access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
132            let supportedTypes: {Type: Bool} = {}
133            supportedTypes[Type<@CricketMoments.NFT>()] = true
134            return supportedTypes
135        }
136
137        /// Returns whether or not the given type is accepted by the collection
138        /// A collection that can accept any type should just return true by default
139        access(all) view fun isSupportedNFTType(type: Type): Bool {
140            return type == Type<@CricketMoments.NFT>()
141        }
142
143        // Return the amount of NFTs stored in the collection
144        access(all) view fun getLength(): Int {
145            return self.getIDs().length
146        }
147    }
148
149    // Creates an empty ShardedCollection and returns it to the caller
150    access(all) fun createEmptyCollection(numBuckets: UInt64): @ShardedCollection {
151        return <-create ShardedCollection(numBuckets: numBuckets)
152    }
153
154    init() {
155        self.ShardedCollectionStoragePath = /storage/CricketMomentsShardedCollection
156    }
157}
158