-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEternalShardedCollection.cdc
152 lines (120 loc) · 5.53 KB
/
EternalShardedCollection.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
150
151
152
/*
Copied from the EternalShardedCollection contract except with
names changed.
*/
import NonFungibleToken from 0xNFTADDRESS
import Eternal from 0xETERNALADDRESS
pub contract EternalShardedCollection {
// ShardedCollection stores a dictionary of Eternal Collections
// A Moment is stored in the field that corresponds to its id % numBuckets
pub resource ShardedCollection: Eternal.MomentCollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic {
// Dictionary of Eternal collections
pub var collections: @{UInt64: Eternal.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] <-! Eternal.createEmptyCollection() as! @Eternal.Collection
i = i + UInt64(1)
}
}
// withdraw removes a Moment from one of the Collections
// 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
// Withdraw the moment
let token <- self.collections[bucket]?.withdraw(withdrawID: withdrawID)!
return <-token
}
// batchWithdraw withdraws multiple tokens and returns them as a Collection
//
// Parameters: ids: an array of the IDs to be withdrawn from the Collection
//
// Returns: @NonFungibleToken.Collection a Collection containing the moments
// that were withdrawn
pub fun batchWithdraw(ids: [UInt64]): @NonFungibleToken.Collection {
var batchCollection <- Eternal.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
pub fun deposit(token: @NonFungibleToken.NFT) {
// Find the bucket this corresponds to
let bucket = token.id % self.numBuckets
// Remove the collection
let collection <- self.collections.remove(key: bucket)!
// Deposit the nft into the bucket
collection.deposit(token: <-token)
// Put the Collection back in storage
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] {
var ids: [UInt64] = []
// Concatenate IDs in all the Collections
for key in self.collections.keys {
for id in self.collections[key]?.getIDs() ?? [] {
ids.append(id)
}
}
return ids
}
// 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"
}
// Get the bucket of the nft to be borrowed
let bucket = id % self.numBuckets
// Find NFT in the collections and borrow a reference
return self.collections[bucket]?.borrowNFT(id: id)!
}
// borrowMoment Returns a borrowed reference to a Moment in the Collection
// so that the caller can read data and call methods from it
// They can use this to read its setID, playID, serialNumber,
// or any of the setData or Play Data associated with it by
// getting the setID or playID and reading those fields from
// the smart contract
//
// Parameters: id: The ID of the NFT to get the reference for
//
// Returns: A reference to the NFT
pub fun borrowMoment(id: UInt64): &Eternal.NFT? {
// Get the bucket of the nft to be borrowed
let bucket = id % self.numBuckets
return self.collections[bucket]?.borrowMoment(id: id) ?? nil
}
// If a transaction destroys the Collection object,
// All the NFTs contained within are also destroyed
destroy() {
destroy self.collections
}
}
// Creates an empty ShardedCollection and returns it to the caller
pub fun createEmptyCollection(numBuckets: UInt64): @ShardedCollection {
return <-create ShardedCollection(numBuckets: numBuckets)
}
}