Smart Contract
NFGv3
A.123cb666996b8432.NFGv3
1import NonFungibleToken from 0x1d7e57aa55817448
2import FungibleToken from 0xf233dcee88fe0abe
3import MetadataViews from 0x1d7e57aa55817448
4import FindForge from 0x097bafa4e0b48eef
5import ViewResolver from 0x1d7e57aa55817448
6
7access(all) contract NFGv3: NonFungibleToken {
8
9 access(all) var totalSupply: UInt64
10
11 access(all) event ContractInitialized()
12 access(all) event Withdraw(id: UInt64, from: Address?)
13 access(all) event Deposit(id: UInt64, to: Address?)
14
15 access(all) let CollectionStoragePath: StoragePath
16 access(all) let CollectionPublicPath: PublicPath
17 access(all) let MinterStoragePath: StoragePath
18
19 access(all) struct Info {
20 access(all) let name: String
21 access(all) let description: String
22 access(all) let thumbnailHash: String
23 access(all) let externalURL: String
24 access(all) let edition: UInt64
25 access(all) let maxEdition: UInt64
26 access(all) let levels: {String: UFix64}
27 access(all) let scalars: {String: UFix64}
28 access(all) let traits: {String: String}
29 access(all) let birthday: UFix64
30 access(all) let medias: {String: String}
31
32 init(name: String, description: String, thumbnailHash: String, edition:UInt64, maxEdition:UInt64, externalURL:String, traits: {String: String}, levels: {String: UFix64}, scalars: {String:UFix64}, birthday: UFix64, medias: {String: String}) {
33 self.name=name
34 self.description=description
35 self.thumbnailHash=thumbnailHash
36 self.edition=edition
37 self.maxEdition=maxEdition
38 self.traits = traits
39 self.levels=levels
40 self.scalars=scalars
41 self.birthday=birthday
42 self.externalURL=externalURL
43 self.medias=medias
44 }
45 }
46
47 access(all) resource NFT: NonFungibleToken.NFT, ViewResolver.Resolver {
48 access(all) let id: UInt64
49
50 access(all) let info: Info
51 access(self) let royalties: MetadataViews.Royalties
52
53 init(
54 info: Info,
55 royalties: MetadataViews.Royalties
56 ) {
57 self.id = self.uuid
58 self.info=info
59 self.royalties = royalties
60 }
61
62 access(all) view fun getID(): UInt64 {
63 return self.id
64 }
65
66 access(all) view fun getViews(): [Type] {
67 return [
68 Type<MetadataViews.Display>(),
69 Type<MetadataViews.Royalties>(),
70 Type<MetadataViews.Editions>(),
71 Type<MetadataViews.Medias>(),
72 Type<MetadataViews.Traits>(),
73 Type<MetadataViews.ExternalURL>(),
74 Type<MetadataViews.NFTCollectionData>(),
75 Type<MetadataViews.NFTCollectionDisplay>()
76 ]
77 }
78
79 access(all) fun resolveView(_ view: Type): AnyStruct? {
80 switch view {
81 case Type<MetadataViews.Traits>():
82 let traits = MetadataViews.Traits([MetadataViews.Trait(name: "Birthday", value: self.info.birthday, displayType: "date", rarity: nil)])
83 for value in self.info.traits.keys {
84 traits.addTrait(MetadataViews.Trait(name: value, value: self.info.traits[value], displayType: "String", rarity: nil))
85 }
86 for value in self.info.scalars.keys {
87 traits.addTrait(MetadataViews.Trait(name: value, value: self.info.scalars[value], displayType: "Number", rarity: nil))
88 }
89 for value in self.info.levels.keys {
90 traits.addTrait(MetadataViews.Trait(name: value, value: self.info.levels[value], displayType: "Number", rarity: MetadataViews.Rarity(score: self.info.levels[value], max: 100.0, description:nil)))
91 }
92 return traits
93 case Type<MetadataViews.Display>():
94 return MetadataViews.Display(
95 name: self.info.name,
96 description: self.info.description,
97 thumbnail: MetadataViews.IPFSFile(
98 cid: self.info.thumbnailHash, path: nil
99 )
100 )
101 case Type<MetadataViews.Editions>():
102 let editionInfo = MetadataViews.Edition(name: "set", number: self.info.edition, max: self.info.maxEdition)
103 let editionList: [MetadataViews.Edition] = [editionInfo]
104 return MetadataViews.Editions(
105 editionList
106 )
107 case Type<MetadataViews.Royalties>():
108 return self.royalties
109 case Type<MetadataViews.ExternalURL>():
110 return MetadataViews.ExternalURL(self.info.externalURL)
111 case Type<MetadataViews.Medias>() :
112 let mediaList : [MetadataViews.Media]=[]
113 for hash in self.info.medias.keys {
114 let mediaType=self.info.medias[hash]!
115 let file= MetadataViews.IPFSFile(
116 cid: hash,
117 path:nil
118 )
119 let m:MetadataViews.Media=MetadataViews.Media(file: file, mediaType: mediaType)
120 mediaList.append(m)
121 }
122 return MetadataViews.Medias(mediaList)
123 case Type<MetadataViews.NFTCollectionData>():
124 return NFGv3.resolveContractView(resourceType: Type<@NFGv3.NFT>(), viewType: Type<MetadataViews.NFTCollectionData>())
125 case Type<MetadataViews.NFTCollectionDisplay>():
126 return NFGv3.resolveContractView(resourceType: Type<@NFGv3.NFT>(), viewType: Type<MetadataViews.NFTCollectionDisplay>())
127 }
128 return nil
129 }
130
131 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
132 return <-NFGv3.createEmptyCollection(nftType:Type<@NFGv3.NFT>())
133 }
134 }
135
136 access(all) view fun getContractViews(resourceType: Type?): [Type] {
137 return [
138 Type<MetadataViews.NFTCollectionData>(),
139 Type<MetadataViews.NFTCollectionDisplay>()
140 ]
141 }
142
143 access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
144 switch viewType {
145 case Type<MetadataViews.NFTCollectionData>():
146 let collectionRef = self.account.storage.borrow<&NFGv3.Collection>(
147 from: NFGv3.CollectionStoragePath
148 ) ?? panic("Could not borrow a reference to the stored collection")
149 let collectionData = MetadataViews.NFTCollectionData(
150 storagePath: NFGv3.CollectionStoragePath,
151 publicPath: NFGv3.CollectionPublicPath,
152 publicCollection: Type<&NFGv3.Collection>(),
153 publicLinkedType: Type<&NFGv3.Collection>(),
154 createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} {
155 return <-NFGv3.createEmptyCollection(nftType:Type<@NFGv3.NFT>())
156 })
157 )
158 return collectionData
159 case Type<MetadataViews.NFTCollectionDisplay>():
160 let square = MetadataViews.Media(
161 file: MetadataViews.IPFSFile(
162 cid: "QmeG1rPaLWmn4uUSjQ2Wbs7QnjxdQDyeadCGWyGwvHTB7c",
163 path: nil
164 ),
165 mediaType: "image/png"
166 )
167 let banner = MetadataViews.Media(
168 file: MetadataViews.IPFSFile(
169 cid: "QmWmDRnSrv8HK5QsiHwUNR4akK95WC8veydq6dnnFbMja1",
170 path: nil
171 ),
172 mediaType: "image/png"
173 )
174 return MetadataViews.NFTCollectionDisplay(
175 name: "NonFunGerbils",
176 description: "The NonFunGerbils are a collaboration between the NonFunGerbils Podcast, their audience and sometimes fabolous artists. Harnessing the power of MEMEs with creative writing and collaboration they create the most dankest, cutest gerbils in the NFT space.",
177 externalURL: MetadataViews.ExternalURL("https://nonfungerbils.com"),
178 squareImage: square,
179 bannerImage: banner,
180 socials: {
181 "twitter": MetadataViews.ExternalURL("https://twitter.com/NonFunGerbils")
182 }
183 )
184 }
185 return nil
186 }
187
188 access(all) resource Collection: NonFungibleToken.Collection, ViewResolver.ResolverCollection {
189 // dictionary of NFT conforming tokens
190 // NFT is a resource type with an `UInt64` ID field
191 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
192
193 init () {
194 self.ownedNFTs <- {}
195 let identifier = "NFGv3NFTCollection"
196 }
197
198 // withdraw removes an NFT from the collection and moves it to the caller
199 access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
200 let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
201
202 emit Withdraw(id: token.id, from: self.owner?.address)
203
204 return <-token
205 }
206
207 // deposit takes a NFT and adds it to the collections dictionary
208 // and adds the ID to the id array
209 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
210 let token <- token as! @NFGv3.NFT
211
212 let id: UInt64 = token.id
213
214 // add the new token to the dictionary which removes the old one
215 let oldToken <- self.ownedNFTs[id] <- token
216
217 emit Deposit(id: id, to: self.owner?.address)
218
219 destroy oldToken
220 }
221
222 // getIDs returns an array of the IDs that are in the collection
223 access(all) view fun getIDs(): [UInt64] {
224 return self.ownedNFTs.keys
225 }
226
227 // borrowNFT gets a reference to an NFT in the collection
228 // so that the caller can read its metadata and call its methods
229 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
230 return &self.ownedNFTs[id]
231 }
232
233 access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver} {
234 let nft = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)
235 let nfgNFT = nft as! &NFGv3.NFT
236 return nfgNFT
237 }
238
239 access(all) view fun getLength(): Int {
240 return self.ownedNFTs.keys.length
241 }
242
243 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
244 return <- create NFGv3.Collection()
245 }
246
247 /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
248 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
249 let supportedTypes: {Type: Bool} = {}
250 supportedTypes[Type<@NFGv3.NFT>()] = true
251 return supportedTypes
252 }
253
254 /// Returns whether or not the given type is accepted by the collection
255 /// A collection that can accept any type should just return true by default
256 access(all) view fun isSupportedNFTType(type: Type): Bool {
257 if type == Type<@NFGv3.NFT>() {
258 return true
259 } else {
260 return false
261 }
262 }
263 }
264
265 // public function that anyone can call to create a new empty collection
266 access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
267 return <- create Collection()
268 }
269
270 access(all) resource Forge: FindForge.Forge {
271 access(FindForge.ForgeOwner) fun mint(platform: FindForge.MinterPlatform, data: AnyStruct, verifier: &FindForge.Verifier) : @{NonFungibleToken.NFT} {
272 let info = data as? Info ?? panic("The data passed in is not in form of NFGv3Info.")
273 let royalties : [MetadataViews.Royalty] = []
274 royalties.append(MetadataViews.Royalty(receiver:platform.platform, cut: platform.platformPercentCut, description: "find forge"))
275 if platform.minterCut != nil {
276 royalties.append(MetadataViews.Royalty(receiver:platform.getMinterFTReceiver(), cut: platform.minterCut!, description: "creator"))
277 }
278
279 // create a new NFT
280 var newNFT <- create NFT(
281 info: info,
282 royalties: MetadataViews.Royalties(royalties)
283 )
284
285 NFGv3.totalSupply = NFGv3.totalSupply + 1
286 return <- newNFT
287 }
288
289 access(FindForge.ForgeOwner) fun addContractData(platform: FindForge.MinterPlatform, data: AnyStruct, verifier: &FindForge.Verifier) {
290 // not used here
291 panic("Not supported for NFGv3 Contract")
292 }
293 }
294
295 access(all) fun getForgeType() : Type {
296 return Type<@Forge>()
297 }
298
299 init() {
300 // Initialize the total supply
301 self.totalSupply = 0
302
303 // Set the named paths
304 self.CollectionStoragePath = /storage/nfgNFTCollection
305 self.CollectionPublicPath = /public/nfgNFTCollection
306 self.MinterStoragePath = /storage/nfgNFTMinter
307
308 // Create a Collection resource and save it to storage
309 let collection <- create Collection()
310 self.account.storage.save(<-collection, to: self.CollectionStoragePath)
311 let collectionCap = self.account.capabilities.storage.issue<&{NonFungibleToken.Collection}>(self.CollectionStoragePath)
312 self.account.capabilities.publish(collectionCap, at: self.CollectionPublicPath)
313
314 FindForge.addForgeType(<- create Forge())
315 emit ContractInitialized()
316 }
317}
318
319