Smart Contract

Collectible

A.f5b0eb433389ac3f.Collectible

Deployed

17h ago
Feb 27, 2026, 11:24:49 PM UTC

Dependents

0 imports
1import NonFungibleToken from 0x1d7e57aa55817448
2import Edition from 0xf5b0eb433389ac3f
3
4pub contract Collectible: NonFungibleToken {
5    // Named Paths   
6    pub let CollectionStoragePath: StoragePath
7    pub let CollectionPublicPath: PublicPath     
8    pub let MinterStoragePath: StoragePath
9    pub let MinterPrivatePath: PrivatePath
10
11    // Events
12    pub event ContractInitialized()
13    pub event Withdraw(id: UInt64, from: Address?)
14    pub event Deposit(id: UInt64, to: Address?)
15    pub event Created(id: UInt64)
16
17    // totalSupply
18    // The total number of NFTs that have been minted
19    //
20    pub var totalSupply: UInt64
21
22    pub resource interface Public {
23        pub let id: UInt64
24        pub let metadata: Metadata
25        // Common number for all copies of the item
26        pub let editionNumber: UInt64
27    }
28
29    pub struct Metadata {
30        // Link to IPFS file
31        pub let link: String   
32        // Name  
33        pub let name: String
34        // Author name
35        pub let author: String
36        // Description
37        pub let description: String
38        // Number of copy
39        pub let edition: UInt64  
40        // Additional properties to use in future
41        pub let properties: AnyStruct    
42
43        init(
44            link:String,          
45            name: String, 
46            author: String,      
47            description: String,        
48            edition: UInt64, 
49            properties: AnyStruct
50    )  {
51            self.link = link             
52            self.name = name
53            self.author = author            
54            self.description = description  
55            self.edition = edition 
56            self.properties = properties             
57        }
58    }
59
60    // NFT
61    // Collectible as an NFT
62    pub resource NFT: NonFungibleToken.INFT, Public {
63        // The token's ID
64        pub let id: UInt64      
65
66        pub let metadata: Metadata
67
68        // Common number for all copies of the item
69        pub let editionNumber: UInt64
70
71        // initializer
72        //
73        init(initID: UInt64, metadata: Metadata, editionNumber: UInt64) {
74            self.id = initID   
75            self.metadata = metadata     
76            self.editionNumber = editionNumber
77        }
78    }
79
80    //Standard NFT collectionPublic interface that can also borrowArt as the correct type
81    pub resource interface CollectionPublic {
82        pub fun deposit(token: @NonFungibleToken.NFT)
83        pub fun getIDs(): [UInt64]
84        pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT  
85        pub fun borrowCollectible(id: UInt64): &Collectible.NFT? {
86            // If the result isn't nil, the id of the returned reference
87            // should be the same as the argument to the function
88            post {
89                (result == nil) || (result?.id == id):
90                    "Cannot borrow collectible reference: The id of the returned reference is incorrect."
91            }
92        }
93        // Common number for all copies of the item
94        pub fun getEditionNumber(id: UInt64): UInt64?
95    }
96
97    // Collection
98    // A collection of NFTs owned by an account
99    //
100    pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic {
101        // dictionary of NFT conforming tokens
102        // NFT is a resource type with an `UInt64` ID field
103        //
104        pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT}
105
106        // withdraw
107        // Removes an NFT from the collection and moves it to the caller
108        //
109        pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT {
110            let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
111
112            emit Withdraw(id: token.id, from: self.owner?.address)
113
114            return <-token 
115        }
116
117        // deposit
118        // Takes a NFT and adds it to the collections dictionary
119        // and adds the ID to the id array
120        //
121        pub fun deposit(token: @NonFungibleToken.NFT) {
122            let token <- token as! @Collectible.NFT
123
124            let id: UInt64 = token.id
125
126            // add the new token to the dictionary which removes the old one
127            let oldToken <- self.ownedNFTs[id] <- token
128
129            emit Deposit(id: id, to: self.owner?.address)
130
131            destroy oldToken
132        }
133
134        // getIDs
135        // Returns an array of the IDs that are in the collection
136        //
137        pub fun getIDs(): [UInt64] {
138            return self.ownedNFTs.keys
139        }
140
141        pub fun getNFT(id: UInt64): &Collectible.NFT {        
142            let ref = &self.ownedNFTs[id] as auth &NonFungibleToken.NFT?
143            return ref as! &Collectible.NFT     
144        }
145  
146        // Common number for all copies of the item
147        pub fun getEditionNumber(id: UInt64): UInt64? {
148            if self.ownedNFTs[id] == nil { 
149                return nil
150            }
151
152            let ref = self.getNFT(id: id)
153
154            return ref.editionNumber
155        }
156
157        // borrowNFT
158        // Gets a reference to an NFT in the collection
159        // so that the caller can read its metadata and call its methods
160        //
161        pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT {
162            return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)!
163        }
164
165        pub fun borrowCollectible(id: UInt64): &Collectible.NFT? {
166            if self.ownedNFTs[id] != nil {
167                let ref = &self.ownedNFTs[id] as auth &NonFungibleToken.NFT?
168                return ref as! &Collectible.NFT?
169            } else {
170                return nil
171            }
172        }
173        
174        // destructor
175        destroy() {
176            destroy self.ownedNFTs
177        }
178
179        // initializer
180        //
181        init () {
182            self.ownedNFTs <- {}
183        }
184    }
185
186    // createEmptyCollection
187    // public function that anyone can call to create a new empty collection
188    //
189    pub fun createEmptyCollection(): @NonFungibleToken.Collection {
190        return <- create Collection()
191    }
192
193    pub resource NFTMinter {
194  
195        pub fun mintNFT(metadata: Metadata, editionNumber: UInt64): @NFT {
196            let editionRef = Collectible.account.getCapability<&{Edition.EditionCollectionPublic}>(Edition.CollectionPublicPath).borrow()! 
197
198            // Check edition info in contract Edition in order to manage commission and all amount of copies of the same item
199            assert(editionRef.getEdition(editionNumber) != nil, message: "Edition does not exist")
200        
201            var newNFT <- create NFT(
202                initID: Collectible.totalSupply,
203                metadata: Metadata(
204                    link: metadata.link,          
205                    name: metadata.name, 
206                    author: metadata.author,      
207                    description: metadata.description,        
208                    edition: metadata.edition, 
209                    properties: metadata.properties           
210                ),
211                editionNumber: editionNumber
212            )
213            emit Created(id: Collectible.totalSupply)
214
215            Collectible.totalSupply = Collectible.totalSupply + UInt64(1)
216
217            return <-newNFT
218        }
219    }
220
221    // structure for display NFTs data
222    pub struct CollectibleData {
223        pub let metadata: Collectible.Metadata
224        pub let id: UInt64
225        pub let editionNumber: UInt64
226        init(metadata: Collectible.Metadata, id: UInt64, editionNumber: UInt64) {
227            self.metadata= metadata
228            self.id=id
229            self.editionNumber=editionNumber
230        }
231    }
232
233    // get info for NFT including metadata
234    pub fun getCollectibleDatas(address:Address) : [CollectibleData] {
235
236        var collectibleData: [CollectibleData] = []
237        let account = getAccount(address)
238
239        if let CollectibleCollection = account.getCapability(self.CollectionPublicPath).borrow<&{Collectible.CollectionPublic}>()  {
240            for id in CollectibleCollection.getIDs() {
241                var collectible = CollectibleCollection.borrowCollectible(id: id) 
242                collectibleData.append(CollectibleData(
243                    metadata: collectible!.metadata,
244                    id: id,
245                    editionNumber: collectible!.editionNumber
246                ))
247            }
248        }
249        return collectibleData
250    } 
251
252    init() {
253        // Initialize the total supply
254        self.totalSupply = 1
255        self.CollectionPublicPath = /public/bloctoXtinglesCollectibleCollection
256        self.CollectionStoragePath = /storage/bloctoXtinglesCollectibleCollection
257        self.MinterStoragePath = /storage/bloctoXtinglesCollectibleMinter
258        self.MinterPrivatePath = /private/bloctoXtinglesCollectibleMinter
259
260        self.account.save<@NonFungibleToken.Collection>(<- Collectible.createEmptyCollection(), to: Collectible.CollectionStoragePath)
261        self.account.link<&{Collectible.CollectionPublic}>(Collectible.CollectionPublicPath, target: Collectible.CollectionStoragePath)
262        
263        let minter <- create NFTMinter()         
264        self.account.save(<-minter, to: self.MinterStoragePath)
265        self.account.link<&Collectible.NFTMinter>(self.MinterPrivatePath, target: self.MinterStoragePath)
266
267        emit ContractInitialized()
268	}
269
270}