Smart Contract

Basketballs

A.eee6bdee2b2bdfc8.Basketballs

Deployed

2h ago
Feb 28, 2026, 09:11:10 PM UTC

Dependents

0 imports
1import NonFungibleToken from 0x1d7e57aa55817448
2
3// Basketballs
4// NFT basketballs!
5//
6access(all) contract Basketballs: NonFungibleToken {
7
8    // Events
9    access(all) event ContractInitialized()
10    access(all) event EditionCreated(editionID: UInt32, name: String, description: String, imageURL: String)
11    access(all) event BasketballMinted(id: UInt64, editionID: UInt32, serialNumber: UInt64)
12    access(all) event Withdraw(id: UInt64, from: Address?)
13    access(all) event Deposit(id: UInt64, to: Address?)
14    access(all) event Destroy(id: UInt64)
15
16    // Named Paths
17    //
18    access(all) let CollectionStoragePath: StoragePath
19    access(all) let CollectionPublicPath: PublicPath
20    access(all) let AdminStoragePath: StoragePath
21
22
23    access(all) var totalSupply: UInt64
24    access(all) var nextEditionID: UInt32
25    access(self) var editions: {UInt32: Edition}
26
27    access(all) struct EditionMetadata {
28        access(all) let editionID: UInt32
29        access(all) let name: String
30        access(all) let description: String
31        access(all) let imageURL: String
32        access(all) let circulatingCount: UInt64
33
34        init(editionID: UInt32, name: String, description: String, imageURL: String, circulatingCount: UInt64) {
35            self.editionID = editionID
36            self.name = name
37            self.description = description
38            self.imageURL = imageURL
39            self.circulatingCount = circulatingCount
40        }
41    }
42
43    access(all) struct Edition {
44       access(all) let editionID: UInt32
45       access(all) let name: String
46       access(all) let description: String
47       access(all) let imageURL: String
48       access(account) var nextSerialInEdition: UInt64
49
50        init(name: String, description: String, imageURL: String) {
51            self.editionID = Basketballs.nextEditionID
52            self.name = name
53            self.description = description
54            self.imageURL = imageURL
55            self.nextSerialInEdition = 1
56
57            Basketballs.nextEditionID = Basketballs.nextEditionID + (1 as UInt32)
58
59            emit EditionCreated(editionID: self.editionID, name: self.name, description: self.description, imageURL: self.imageURL)
60        }
61
62        access(all) fun mintBasketball(): @NFT {
63            let basketball: @NFT <- create NFT(editionID: self.editionID, serialNumber: self.nextSerialInEdition)
64
65            self.nextSerialInEdition = self.nextSerialInEdition + (1 as UInt64)
66
67            Basketballs.editions[self.editionID] = self
68
69            return <-basketball
70        }
71
72        access(all) fun mintBasketballs(quantity: UInt64): @Collection {
73            let newCollection <- create Collection()
74
75            var i: UInt64 = 0
76            while i < quantity {
77                newCollection.deposit(token: <- self.mintBasketball())
78                i = i + 1
79            }
80
81            return <- newCollection
82        }
83    }
84
85    // NFT
86    // A Basketball as an NFT
87    //
88    access(all) resource NFT: NonFungibleToken.NFT {
89		access(all) event ResourceDestroyed(id: UInt64 = self.id)
90
91        access(all) let id: UInt64
92        access(all) let editionID: UInt32
93        access(all) let serialNumber: UInt64
94
95        init(editionID: UInt32, serialNumber: UInt64) {
96            Basketballs.totalSupply = Basketballs.totalSupply + (1 as UInt64)
97            self.id = Basketballs.totalSupply
98            self.editionID = editionID
99            self.serialNumber = serialNumber
100
101            emit BasketballMinted(id: self.id, editionID: self.editionID, serialNumber: self.serialNumber)
102        }
103
104
105        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
106            panic("TODO")
107        }
108
109        access(all) view fun getViews(): [Type] {
110            panic("TODO")
111        }
112
113        access(all) view fun resolveView(_ view: Type): AnyStruct? {
114            panic("TODO")
115        }
116}
117
118    access(all) resource interface BasketballsCollectionPublic {}
119
120    // Collection
121    // A collection of Basketball NFTs owned by an account
122    //
123    access(all) resource Collection: NonFungibleToken.Collection, BasketballsCollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic {
124        // dictionary of NFT conforming tokens
125        // NFT is a resource type with an UInt64 ID field
126        //
127        access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
128
129        // withdraw
130        // Removes an NFT from the collection and moves it to the caller
131        //
132        access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
133            let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
134
135            emit Withdraw(id: token.id, from: self.owner?.address)
136
137            return <-token
138        }
139
140        // deposit
141        // Takes a NFT and adds it to the collections dictionary
142        // and adds the ID to the id array
143        //
144        access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
145            let token <- token as! @Basketballs.NFT
146
147            let id: UInt64 = token.id
148
149            // add the new token to the dictionary which removes the old one
150            let oldToken <- self.ownedNFTs[id] <- token
151
152            emit Deposit(id: id, to: self.owner?.address)
153
154            destroy oldToken
155        }
156
157        // getIDs
158        // Returns an array of the IDs that are in the collection
159        //
160        access(all) view fun getIDs(): [UInt64] {
161            return self.ownedNFTs.keys
162        }
163
164        // borrowNFT
165        // Gets a reference to an NFT in the collection
166        // so that the caller can read its metadata and call its methods
167        //
168        access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
169            return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)
170        }
171
172        // borrowBasketball
173        // Gets a reference to an NFT in the collection as a Basketball,
174        // exposing all of its fields (including the typeID).
175        // This is safe as there are no functions that can be called on the Basketball.
176        //
177        access(all) fun borrowBasketball(id: UInt64): &Basketballs.NFT? {
178            if self.ownedNFTs[id] != nil {
179                let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
180                return ref as! &Basketballs.NFT
181            } else {
182                return nil
183            }
184        }
185
186        // initializer
187        //
188        init () {
189            self.ownedNFTs <- {}
190        }
191    
192        access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
193            panic("TODO")
194        }
195
196        access(all) view fun isSupportedNFTType(type: Type): Bool {
197            panic("TODO")
198        }
199
200        access(all) view fun getLength(): Int {
201            panic("TODO")
202        }
203                /// createEmptyCollection creates an empty Collection of the same type
204        /// and returns it to the caller
205        /// @return A an empty collection of the same type
206        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
207            return <-Basketballs.createEmptyCollection(nftType: Type<@Basketballs.NFT>())
208        }
209}
210
211    access(all) resource Admin {
212
213        access(all) fun createEdition(name: String, description: String, imageURL: String): UInt32 {
214            let edition = Edition(name: name, description: description, imageURL: imageURL)
215
216            Basketballs.editions[edition.editionID] = edition
217
218            return edition.editionID
219        }
220
221        access(all) fun mintBasketball(editionID: UInt32): @NFT {
222            pre {
223                Basketballs.editions[editionID] != nil: "Mint failed: Edition does not exist"
224            }
225
226            let edition: Edition = Basketballs.editions[editionID]!;
227
228            let basketball: @NFT <- edition.mintBasketball()
229
230            return <-basketball
231        }
232
233        access(all) fun mintBasketballs(editionID: UInt32, quantity: UInt64): @Collection {
234            pre {
235                Basketballs.editions[editionID] != nil: "Mint failed: Edition does not exist"
236            }
237
238            let edition: Edition = Basketballs.editions[editionID]!;
239
240            let collection: @Collection <- edition.mintBasketballs(quantity: quantity)
241
242            return <-collection
243        }
244
245        access(all) fun createNewAdmin(): @Admin {
246            return <- create Admin()
247        }
248    }
249
250    access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
251        return <- create Collection()
252    }
253
254    // fetch
255    // Get a reference to a Basketball from an account's Collection, if available.
256    // If an account does not have a Basketballs.Collection, panic.
257    // If it has a collection but does not contain the itemId, return nil.
258    // If it has a collection and that collection contains the itemId, return a reference to that.
259    //
260    access(all) fun fetch(_ from: Address, itemID: UInt64): &Basketballs.NFT? {
261        let account = getAccount(from)
262        let collection = account.capabilities.borrow<&Basketballs.Collection>(/public/BasketballsCollection)
263            ?? panic("Couldn't get collection")
264
265        // We trust Basketballs.Collection.borowBasketball to get the correct itemID
266        // (it checks it before returning it).
267        return collection.borrowBasketball(id: itemID)
268    }
269
270     access(all) fun getAllEditions(): [Edition] {
271        return self.editions.values
272    }
273
274    access(all) fun getEditionMetadata(editionID: UInt32): EditionMetadata {
275        let edition = self.editions[editionID]!
276        let metadata = EditionMetadata(editionID: edition.editionID, name: edition.name, description: edition.description, imageURL: edition.imageURL, circulatingCount: edition.nextSerialInEdition - (1 as UInt64))
277        return metadata
278    }
279
280    // initializer
281    //
282	init() {
283        // Set our named paths
284        self.CollectionStoragePath = /storage/BasketballsCollection
285        self.CollectionPublicPath = /public/BasketballsCollection
286        self.AdminStoragePath = /storage/BasketballsAdmin
287
288        // Initialize the total supply
289         self.totalSupply = 0
290        self.editions = {}
291        self.nextEditionID = 1
292
293        self.account.storage.save(<- create Admin(), to: self.AdminStoragePath)
294
295        emit ContractInitialized()
296	}
297
298    access(all) view fun getContractViews(resourceType: Type?): [Type] {
299        panic("TODO")
300    }
301
302    access(all) view fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
303        panic("TODO")
304    }
305}
306