Smart Contract

NFGv3

A.123cb666996b8432.NFGv3

Deployed

6d ago
Feb 21, 2026, 06:56:45 PM UTC

Dependents

19 imports
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