Smart Contract
CharityNFT
A.097bafa4e0b48eef.CharityNFT
1
2import NonFungibleToken from 0x1d7e57aa55817448
3import MetadataViews from 0x1d7e57aa55817448
4import ViewResolver from 0x1d7e57aa55817448
5
6access(all) contract CharityNFT: NonFungibleToken {
7
8 access(all) var totalSupply: UInt64
9
10 access(all) let CollectionStoragePath: StoragePath
11 access(all) let CollectionPublicPath: PublicPath
12
13 access(all) event ContractInitialized()
14 access(all) event Withdraw(id: UInt64, from: Address?)
15 access(all) event Deposit(id: UInt64, to: Address?)
16 access(all) event Minted(id: UInt64, metadata: {String:String}, to:Address)
17
18 access(all) resource NFT: NonFungibleToken.NFT, Public, ViewResolver.Resolver {
19 access(all) let id: UInt64
20
21 access(self) let metadata: {String: String}
22
23 init(initID: UInt64, metadata: {String : String}) {
24 self.id = initID
25 self.metadata = metadata
26 }
27
28 access(all) view fun getMetadata() : { String : String} {
29 return self.metadata
30 }
31
32 access(all) view fun getID(): UInt64 {
33 return self.id
34 }
35
36 access(all) view fun getViews(): [Type] {
37 return [
38 Type<MetadataViews.Display>() ,
39 Type<MetadataViews.Royalties>() ,
40 Type<MetadataViews.ExternalURL>() ,
41 Type<MetadataViews.NFTCollectionDisplay>() ,
42 Type<MetadataViews.NFTCollectionData>() ,
43 Type<MetadataViews.Edition>()
44 ]
45 }
46
47 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
48 return <-CharityNFT.createEmptyCollection(nftType:Type<@CharityNFT.NFT>())
49 }
50
51 access(all) fun resolveView(_ view: Type): AnyStruct? {
52 switch view {
53
54 case Type<MetadataViews.Display>() :
55 // just in case there is no "image" key, return the general bronze image
56 let image = self.metadata["thumbnail"] ?? "ipfs://QmcxXHLADpcw5R7xi6WmPjnKAEayK3eiEh85gzjgdzfwN6"
57 return MetadataViews.Display(
58 name: self.metadata["name"] ?? "Neo Charity 2021" ,
59 description: self.metadata["description"] ?? "Neo Charity 2021",
60 thumbnail: MetadataViews.IPFSFile(
61 cid: image.slice(from: "ipfs://".length, upTo: image.length) ,
62 path: nil
63 )
64 )
65
66 case Type<MetadataViews.Royalties>() :
67 // No Royalties implemented
68 return MetadataViews.Royalties([])
69
70 case Type<MetadataViews.ExternalURL>() :
71 return MetadataViews.ExternalURL("http://find.xyz/neoCharity")
72
73 case Type<MetadataViews.NFTCollectionDisplay>() :
74 return MetadataViews.NFTCollectionDisplay(
75 name: "Neo Charity 2021",
76 description: "This collection is to show participation in the Neo Collectibles x Flowverse Charity Auction in 2021.",
77 externalURL: MetadataViews.ExternalURL("http://find.xyz/neoCharity"),
78 squareImage: MetadataViews.Media(file: MetadataViews.HTTPFile(url: "https://pbs.twimg.com/profile_images/1467546091780550658/R1uc6dcq_400x400.jpg") , mediaType: "image"),
79 bannerImage: MetadataViews.Media(file: MetadataViews.HTTPFile(url: "https://pbs.twimg.com/profile_banners/1448245049666510848/1652452073/1500x500") , mediaType: "image"),
80 socials: {
81 "Twitter" : MetadataViews.ExternalURL("https://twitter.com/findonflow") ,
82 "Discord" : MetadataViews.ExternalURL("https://discord.gg/95P274mayM")
83 }
84 )
85
86 case Type<MetadataViews.NFTCollectionData>() :
87 return CharityNFT.resolveContractView(resourceType: Type<@CharityNFT.Collection>(), viewType: Type<MetadataViews.NFTCollectionData>()) as! MetadataViews.NFTCollectionData
88
89 case Type<MetadataViews.Edition>() :
90 let edition = self.metadata["edition"]
91 let maxEdition = self.metadata["maxEdition"]
92 if edition == nil || maxEdition == nil {
93 return nil
94 }
95 let editionNumber = self.parseUInt64(edition!)
96 let maxEditionNumber = self.parseUInt64(maxEdition!)
97 if editionNumber == nil {
98 return nil
99 }
100 return MetadataViews.Edition(
101 name: nil,
102 number: editionNumber!,
103 max: editionNumber
104 )
105
106 }
107 return nil
108
109 }
110
111 access(all) view fun parseUInt64(_ string: String) : UInt64? {
112 let chars : {Character : UInt64} = {
113 "0" : 0 ,
114 "1" : 1 ,
115 "2" : 2 ,
116 "3" : 3 ,
117 "4" : 4 ,
118 "5" : 5 ,
119 "6" : 6 ,
120 "7" : 7 ,
121 "8" : 8 ,
122 "9" : 9
123 }
124 var number : UInt64 = 0
125 var i = 0
126 while i < string.length {
127 if let n = chars[string[i]] {
128 number = number * 10 + n
129 } else {
130 return nil
131 }
132 i = i + 1
133 }
134 return number
135 }
136
137 }
138
139 access(all) view fun getContractViews(resourceType: Type?): [Type] {
140 return [
141 Type<MetadataViews.NFTCollectionData>(),
142 Type<MetadataViews.NFTCollectionDisplay>()
143 ]
144 }
145
146 access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
147 switch viewType {
148
149 case Type<MetadataViews.NFTCollectionDisplay>() :
150 return MetadataViews.NFTCollectionDisplay(
151 name: "Neo Charity 2021",
152 description: "This collection is to show participation in the Neo Collectibles x Flowverse Charity Auction in 2021.",
153 externalURL: MetadataViews.ExternalURL("http://find.xyz/neoCharity"),
154 squareImage: MetadataViews.Media(file: MetadataViews.HTTPFile(url: "https://pbs.twimg.com/profile_images/1467546091780550658/R1uc6dcq_400x400.jpg") , mediaType: "image"),
155 bannerImage: MetadataViews.Media(file: MetadataViews.HTTPFile(url: "https://pbs.twimg.com/profile_banners/1448245049666510848/1652452073/1500x500") , mediaType: "image"),
156 socials: {
157 "Twitter" : MetadataViews.ExternalURL("https://twitter.com/findonflow") ,
158 "Discord" : MetadataViews.ExternalURL("https://discord.gg/95P274mayM")
159 }
160 )
161
162 case Type<MetadataViews.NFTCollectionData>():
163 let collectionData = MetadataViews.NFTCollectionData(
164 storagePath: CharityNFT.CollectionStoragePath,
165 publicPath: CharityNFT.CollectionPublicPath,
166 publicCollection: Type<&CharityNFT.Collection>(),
167 publicLinkedType: Type<&CharityNFT.Collection>(),
168 createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} {
169 return <-CharityNFT.createEmptyCollection(nftType:Type<@CharityNFT.NFT>())
170 })
171 )
172 return collectionData
173 }
174 return nil
175 }
176
177 //The public interface can show metadata and the content for the Art piece
178 access(all) resource interface Public {
179 access(all) let id: UInt64
180 access(all) view fun getMetadata() : {String : String}
181 }
182
183 //Standard NFT collectionPublic interface that can also borrowArt as the correct type
184 access(all) resource interface CollectionPublic {
185 access(all) fun deposit(token: @{NonFungibleToken.NFT})
186 access(all) view fun getIDs(): [UInt64]
187 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}?
188 access(all) fun borrowCharity(id: UInt64): &{Public}?
189 }
190
191 access(all) resource Collection: NonFungibleToken.Collection, CollectionPublic , ViewResolver.ResolverCollection{
192 // dictionary of NFT conforming tokens
193 // NFT is a resource type with an `UInt64` ID field
194 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
195
196 init () {
197 self.ownedNFTs <- {}
198 let identifier = "charityNFTCollection"
199 }
200
201 // withdraw removes an NFT from the collection and moves it to the caller
202 access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
203 let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT. WithdrawID : ".concat(withdrawID.toString()))
204
205 emit Withdraw(id: token.id, from: self.owner?.address)
206
207 return <-token
208 }
209
210 // deposit takes a NFT and adds it to the collections dictionary
211 // and adds the ID to the id array
212 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
213 let token <- token as! @CharityNFT.NFT
214
215 let id: UInt64 = token.id
216
217 // add the new token to the dictionary which removes the old one
218 let oldToken <- self.ownedNFTs[id] <- token
219
220 emit Deposit(id: id, to: self.owner?.address)
221
222 destroy oldToken
223 }
224
225 // getIDs returns an array of the IDs that are in the collection
226 access(all) view fun getIDs(): [UInt64] {
227 return self.ownedNFTs.keys
228 }
229
230 // borrowNFT gets a reference to an NFT in the collection
231 // so that the caller can read its metadata and call its methods
232 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
233 return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
234 }
235
236 //borrow charity
237 access(all) fun borrowCharity(id: UInt64): &{CharityNFT.Public}? {
238 if self.ownedNFTs[id] != nil {
239 let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
240 return ref as! &NFT
241 } else {
242 return nil
243 }
244 }
245
246 //borrow view resolver
247 access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver} {
248 if self.ownedNFTs[id] == nil {
249 panic("NFT does not exist. ID : ".concat(id.toString()))
250 }
251
252 let nft = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
253 return nft as! &CharityNFT.NFT
254 }
255
256 /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
257 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
258 let supportedTypes: {Type: Bool} = {}
259 supportedTypes[Type<@CharityNFT.NFT>()] = true
260 return supportedTypes
261 }
262
263 /// Returns whether or not the given type is accepted by the collection
264 /// A collection that can accept any type should just return true by default
265 access(all) view fun isSupportedNFTType(type: Type): Bool {
266 if type == Type<@CharityNFT.NFT>() {
267 return true
268 } else {
269 return false
270 }
271 }
272
273 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
274 return <- create CharityNFT.Collection()
275 }
276
277 access(all) view fun getLength(): Int {
278 return self.ownedNFTs.keys.length
279 }
280 }
281
282 // public function that anyone can call to create a new empty collection
283 access(all) fun createEmptyCollection(nftType:Type): @{NonFungibleToken.Collection} {
284 return <- create Collection()
285 }
286
287
288 // mintNFT mints a new NFT with a new ID
289 // and deposit it in the recipients collection using their collection reference
290 access(account) fun mintCharity(metadata: {String:String}, recipient: Capability<&{NonFungibleToken.Collection}>) {
291 // create a new NFT
292 var newNFT <- create NFT(initID: CharityNFT.totalSupply, metadata:metadata)
293
294 // deposit it in the recipient's account using their reference
295 let collectionRef = recipient.borrow() ?? panic("Cannot borrow reference to collection public. ")
296 collectionRef.deposit(token: <-newNFT)
297 emit Minted(id: CharityNFT.totalSupply, metadata:metadata, to: recipient.address)
298
299 CharityNFT.totalSupply = CharityNFT.totalSupply + 1
300 }
301
302 init() {
303 // Initialize the total supply
304 self.totalSupply = 0
305
306 emit ContractInitialized()
307 self.CollectionPublicPath=/public/findCharityCollection
308 self.CollectionStoragePath=/storage/findCharityCollection
309 }
310}
311
312