forked from dapperlabs/nba-smart-contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TopShotShardedCollection.cdc
149 lines (111 loc) · 5.15 KB
/
TopShotShardedCollection.cdc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
Description: Central Collection for a large number of topshot
NFTs
authors: Joshua Hannan joshua.hannan@dapperlabs.com
Bastian Muller bastian@dapperlabs.com
*/
import NonFungibleToken from 0x02
import TopShot from 0x03
pub contract TopShotShardedCollection {
// Collection is a resource that every user who owns NFTs
// will store in their account to manage their NFTS
//
pub resource ShardedCollection: TopShot.MomentCollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic {
// Dictionary of Moment conforming tokens
// NFT is a resource type with a UInt64 ID field
pub var collections: @{UInt64: NonFungibleToken.Collection}
// the number of buckets to split moments into
// this makes storage more efficient and performant
pub let numBuckets: UInt64
init(numBuckets: UInt64) {
self.collections <- {}
self.numBuckets = numBuckets
// Create a new empty collection for each bucket
var i: UInt64 = 0
while i < numBuckets {
self.collections[i] <-! TopShot.createEmptyCollection()
i = i + UInt64(1)
}
}
// withdraw removes an Moment from the collection and moves it to the caller
pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT {
post {
result.id == withdrawID: "The ID of the withdrawn NFT is incorrect"
}
// find the bucket it should be withdrawn from
let bucket = withdrawID % self.numBuckets
// remove the collection from the dictionary
let collection <- self.collections.remove(key: bucket)!
// withdraw the nft
let token <- collection.withdraw(withdrawID: withdrawID)
// put the collection back in the dictionary
self.collections[bucket] <-! collection
return <-token
}
// batchWithdraw withdraws multiple tokens and returns them as a Collection
pub fun batchWithdraw(ids: [UInt64]): @NonFungibleToken.Collection {
var batchCollection <- TopShot.createEmptyCollection()
// iterate through the ids and withdraw them from the collection
for id in ids {
batchCollection.deposit(token: <-self.withdraw(withdrawID: id))
}
return <-batchCollection
}
// deposit takes a Moment and adds it to the collections dictionary
// and adds the ID to the id array
pub fun deposit(token: @NonFungibleToken.NFT) {
// find the bucket this corresponds to
let bucket = token.id % UInt64(self.numBuckets)
// remove the collection from the dictionary
let collection <- self.collections.remove(key: bucket)!
// deposit the nft
collection.deposit(token: <-token)
// store the collection back in the dictionary
self.collections[bucket] <-! collection
}
// batchDeposit takes a Collection object as an argument
// and deposits each contained NFT into this collection
pub fun batchDeposit(tokens: @NonFungibleToken.Collection) {
let keys = tokens.getIDs()
// iterate through the keys in the collection and deposit each one
for key in keys {
self.deposit(token: <-tokens.withdraw(withdrawID: key))
}
destroy tokens
}
// getIDs returns an array of the IDs that are in the collection
pub fun getIDs(): [UInt64] {
// concatenate IDs in all the collections
var idArray: [UInt64] = []
for key in self.collections.keys {
idArray.concat(self.collections[key]?.getIDs() ?? [])
}
return idArray
}
// borrowNFT Returns a borrowed reference to a Moment in the collection
// so that the caller can read data and call methods from it
pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT {
post {
result.id == id: "The ID of the reference is incorrect"
}
let bucket = id % self.numBuckets
let ref = self.collections[bucket]?.borrowNFT(id: id)!
// find NFT in the collections and borrow a reference
return ref
}
// If a transaction destroys the Collection object,
// All the NFTs contained within are also destroyed
destroy() {
destroy self.collections
}
}
pub fun createEmptyCollection(numBuckets: UInt64): @ShardedCollection {
return <-create ShardedCollection(numBuckets: numBuckets)
}
init() {
// Put a new Collection in storage
self.account.save<@ShardedCollection>(<- create ShardedCollection(numBuckets: 32), to: /storage/ShardedMomentCollection)
// create a public capability for the collection
self.account.link<&{TopShot.MomentCollectionPublic}>(/public/ShardedMomentCollection, target: /storage/ShardedMomentCollection)
}
}