Smart Contract
Collectible
A.f5b0eb433389ac3f.Collectible
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}