Smart Contract

GroundWork29

A.440776a8205e9f80.GroundWork29

Deployed

1d ago
Feb 26, 2026, 09:44:39 PM UTC

Dependents

0 imports
1import NonFungibleToken from 0x1d7e57aa55817448
2import MetadataViews from 0x1d7e57aa55817448
3import ViewResolver from 0x1d7e57aa55817448
4
5access(all) contract GroundWork29: NonFungibleToken {
6    access(all) event ContractInitialized()
7    access(all) event Withdraw(id: UInt64, from: Address?)
8    access(all) event Deposit(id: UInt64, to: Address?)
9    access(all) event PublishedMinted(id: UInt64, name: String, ipfsLink: String, type: UInt64)
10
11    access(all) let CollectionStoragePath: StoragePath
12    access(all) let CollectionPublicPath: PublicPath
13    access(all) let MinterPublishedPath: StoragePath
14
15    access(all) var totalSupply: UInt64
16    access(all) var libraryPassTotalSupply: UInt64
17    access(all) var willoTotalSupply: UInt64
18
19    access(all) resource NFT: NonFungibleToken.NFT {
20        access(all) let serialId: UInt64
21        access(all) let id: UInt64
22        access(all) let name: String
23        access(all) let ipfsLink: String
24        access(all) let type: UInt64
25
26        init(serialId: UInt64, initID: UInt64, name: String, ipfsLink: String, type: UInt64) {
27            self.serialId = serialId
28            self.id = initID
29            self.name = name
30            self.ipfsLink = ipfsLink
31            self.type= type
32        }
33
34        /// createEmptyCollection creates an empty Collection
35        /// and returns it to the caller so that they can own NFTs
36        /// @{NonFungibleToken.Collection}
37        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
38            return <-GroundWork29.createEmptyCollection(nftType: Type<@GroundWork29.NFT>())
39        }
40
41        access(all) view fun getViews(): [Type] {
42            return [
43                Type<MetadataViews.Display>(),
44                Type<MetadataViews.Royalties>(),
45                Type<MetadataViews.ExternalURL>(),
46                Type<MetadataViews.NFTCollectionData>(),
47                Type<MetadataViews.NFTCollectionDisplay>(),
48                Type<MetadataViews.Serial>(),
49                Type<MetadataViews.EVMBridgedMetadata>()
50            ]
51        }
52
53        access(all) fun resolveView(_ view: Type): AnyStruct? {
54            let url = "https://ipfs.io/ipfs/".concat(self.ipfsLink)
55            switch view {
56                case Type<MetadataViews.Display>():
57                    return MetadataViews.Display(
58                        name: self.name,
59                        description: "The life of a student athlete competing in the NCAA is a lifestyle that is glorified by many, but only truly known by few.On the surface, the life of a student athlete may look easy, but underneath the exterior many tough and demanding experiences are endured.Although some will get the opportunity to play professionally in their respective sports, the reality is that 98% of student athletes who graduate from these prestigious institutions will transition out of sports -- making a very difficult transition at times -- and become a professional in a totally different field. \n\n Registration group element - USA \n Registrant element - Published NFT \n Publication element - Edition #1 \n ISBN - (13-Digit): 978-1-932450-28-6 \n",
60                        thumbnail: MetadataViews.IPFSFile(
61                            cid: self.ipfsLink,
62                            path: nil
63                        )
64                    )
65                case Type<MetadataViews.Royalties>():
66                    var royalties: [MetadataViews.Royalty] = []
67                    return MetadataViews.Royalties(royalties)
68                case Type<MetadataViews.Serial>():
69                    return MetadataViews.Serial(
70                        self.serialId
71                    )
72                case Type<MetadataViews.ExternalURL>():
73                    return MetadataViews.ExternalURL(url)
74
75                case Type<MetadataViews.NFTCollectionData>():
76                    return GroundWork29.resolveContractView(resourceType: Type<@GroundWork29.NFT>(), viewType: Type<MetadataViews.NFTCollectionData>())
77
78                case Type<MetadataViews.NFTCollectionDisplay>():
79                    return GroundWork29.resolveContractView(resourceType: Type<@GroundWork29.NFT>(), viewType: Type<MetadataViews.NFTCollectionDisplay>())
80            
81                case Type<MetadataViews.EVMBridgedMetadata>():
82                    // Implementing this view gives the project control over how the bridged NFT is represented as an
83                    // ERC721 when bridged to EVM on Flow via the public infrastructure bridge.
84
85                    // Get the contract-level name and symbol values
86                    let contractLevel = GroundWork29.resolveContractView(
87                            resourceType: nil,
88                            viewType: Type<MetadataViews.EVMBridgedMetadata>()
89                        ) as! MetadataViews.EVMBridgedMetadata?
90                        ?? panic("Could not resolve contract-level EVMBridgedMetadata")
91                    // Compose the token-level URI based on a base URI and the token ID, pointing to a JSON file. This
92                    // would be a file you've uploaded and are hosting somewhere - in this case HTTP, but this could be
93                    // IPFS, S3, a data URL containing the JSON directly, etc.
94                    let baseURI = "https://ipfs.io/ipfs/".concat(self.ipfsLink)
95                    let uriValue = self.id.toString().concat(".json")
96
97                    return MetadataViews.EVMBridgedMetadata(
98                        name: contractLevel.name,
99                        symbol: contractLevel.symbol,
100                        uri: MetadataViews.URI(
101                            baseURI: baseURI, // defining baseURI results in a concatenation of baseURI and value
102                            value: self.id.toString().concat(".json")
103                        )
104                    )
105            }
106            return nil
107        }
108    }
109
110    access(all) resource interface GroundWork29CollectionPublic {}
111
112    access(all) resource Collection: NonFungibleToken.Collection, GroundWork29CollectionPublic {
113        access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
114
115        init () {
116            self.ownedNFTs <- {}
117        }
118
119        /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
120        access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
121            let supportedTypes: {Type: Bool} = {}
122            supportedTypes[Type<@GroundWork29.NFT>()] = true
123            return supportedTypes
124        }
125
126        /// Returns whether or not the given type is accepted by the collection
127        /// A collection that can accept any type should just return true by default
128        access(all) view fun isSupportedNFTType(type: Type): Bool {
129            return type == Type<@GroundWork29.NFT>()
130        }
131
132        access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
133            let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
134
135            emit Withdraw(id: token.id, from: self.owner?.address)
136
137            return <-token
138        }
139
140        access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
141            let token <- token as! @GroundWork29.NFT
142
143            let id: UInt64 = token.id
144
145            let oldToken <- self.ownedNFTs[id] <- token
146
147            emit Deposit(id: id, to: self.owner?.address)
148
149            destroy oldToken
150        }
151
152        access(all) view fun getIDs(): [UInt64] {
153            return self.ownedNFTs.keys
154        }
155
156        /// Gets the amount of NFTs stored in the collection
157        access(all) view fun getLength(): Int {
158            return self.ownedNFTs.length
159        }
160
161        access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
162            return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)
163        }
164
165        access(all) view fun borrowGroundWork29(id: UInt64): &GroundWork29.NFT? {
166            if self.ownedNFTs[id] != nil {
167                let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
168                return ref as! &GroundWork29.NFT
169            } else {
170                return nil
171            }
172        }
173
174        access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
175            let nft = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
176            let publishedNFT = nft as! &GroundWork29.NFT
177            return publishedNFT as &{ViewResolver.Resolver}
178        }
179
180        /// createEmptyCollection creates an empty Collection of the same type
181        /// and returns it to the caller
182        /// @return A an empty collection of the same type
183        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
184            return <-GroundWork29.createEmptyCollection(nftType: Type<@GroundWork29.NFT>())
185        } 
186    }
187
188    access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
189        return <- create Collection()
190    }
191
192    /// Function that returns all the Metadata Views implemented by a Non Fungible Token
193    ///
194    /// @return An array of Types defining the implemented views. This value will be used by
195    ///         developers to know which parameter to pass to the resolveView() method.
196    ///
197    access(all) view fun getContractViews(resourceType: Type?): [Type] {
198        return [
199            Type<MetadataViews.NFTCollectionData>(),
200            Type<MetadataViews.NFTCollectionDisplay>(),
201            Type<MetadataViews.EVMBridgedMetadata>()
202        ]
203    }
204
205    /// Function that resolves a metadata view for this contract.
206    ///
207    /// @param view: The Type of the desired view.
208    /// @return A structure representing the requested view.
209    ///
210    access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
211        switch viewType {
212            case Type<MetadataViews.NFTCollectionData>():
213                let collectionData = MetadataViews.NFTCollectionData(
214                    storagePath: GroundWork29.CollectionStoragePath,
215                    publicPath: GroundWork29.CollectionPublicPath,
216                    publicCollection: Type<&GroundWork29.Collection>(),
217                    publicLinkedType: Type<&GroundWork29.Collection>(),
218                    createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} {
219                        return <-GroundWork29.createEmptyCollection(nftType: Type<@GroundWork29.NFT>())
220                    })
221                )
222                return collectionData
223            case Type<MetadataViews.NFTCollectionDisplay>():
224                let media = MetadataViews.Media(
225                    file: MetadataViews.HTTPFile(
226                        url: "https://publishednft.io/logo-desktop.png"
227                    ),
228                    mediaType: "image/png"
229                )
230                return MetadataViews.NFTCollectionDisplay(
231                    name: "The Published NFT Collection",
232                    description: "Published NFT is a blockchain eBook publishing platform built on the Flow blockchain, where authors can publish eBooks, Lyrics, Comics, Magazines, Articles, Poems, Recipes, Movie Scripts, Computer Language, etc.",
233                    externalURL: MetadataViews.ExternalURL("https://publishednft.io/"),
234                    squareImage: media,
235                    bannerImage: media,
236                    socials: {
237                        "twitter": MetadataViews.ExternalURL("https://twitter.com/publishednft/"),
238                        "discord": MetadataViews.ExternalURL("https://discord.gg/ct5RPudqpG"),
239                        "instagram": MetadataViews.ExternalURL("https://www.instagram.com/publishednft/"),
240                        "telegram": MetadataViews.ExternalURL("https://t.me/published_nft"),
241                        "reddit": MetadataViews.ExternalURL("https://www.reddit.com/user/PublishedNFT")
242                    }
243                )
244            case Type<MetadataViews.EVMBridgedMetadata>():
245                // Implementing this view gives the project control over how the bridged NFT is represented as an ERC721
246                // when bridged to EVM on Flow via the public infrastructure bridge.
247
248                // Compose the contract-level URI. In this case, the contract metadata is located on some HTTP host,
249                // but it could be IPFS, S3, a data URL containing the JSON directly, etc.
250                return MetadataViews.EVMBridgedMetadata(
251                    name: "GroundWork29",
252                    symbol: "GW29",
253                    uri: MetadataViews.URI(
254                        baseURI: nil, // setting baseURI as nil sets the given value as the uri field value
255                        value: "https://example-nft.onflow.org/contract-metadata.json"
256                    )
257                )
258        }
259        return nil
260    }
261
262    access(all) resource PublishedMinter{
263        access(all) fun mintLibraryPass(_name: String, _ipfsLink: String): @GroundWork29.NFT?{          
264          
265          if GroundWork29.libraryPassTotalSupply == 9999 {return nil}
266          
267          let libraryPassNft <- create GroundWork29.NFT(
268            serialId: GroundWork29.libraryPassTotalSupply,
269            initID: GroundWork29.totalSupply,
270            name: _name,
271            ipfsLink: _ipfsLink,
272            type: 1
273          )
274
275          emit PublishedMinted(id: GroundWork29.totalSupply, name: _name, ipfsLink: _ipfsLink, type: 1)
276
277          GroundWork29.totalSupply = GroundWork29.totalSupply + (1 as UInt64)
278          GroundWork29.libraryPassTotalSupply = GroundWork29.libraryPassTotalSupply + (1 as UInt64)
279
280          return <- libraryPassNft
281        }
282
283        access(all) fun mintWillo(_name: String, _ipfsLink: String): @GroundWork29.NFT?{
284          
285          if GroundWork29.willoTotalSupply == 100 {return nil}
286          
287          let willoNft <- create GroundWork29.NFT(
288            serialId: GroundWork29.willoTotalSupply,
289            initID: GroundWork29.totalSupply,   
290            name: _name,
291            ipfsLink: _ipfsLink,
292            type: 1
293          )
294          
295          emit PublishedMinted(id: GroundWork29.totalSupply, name: _name, ipfsLink: _ipfsLink, type: 2)
296
297          GroundWork29.totalSupply = GroundWork29.totalSupply + (1 as UInt64)
298          GroundWork29.willoTotalSupply = GroundWork29.willoTotalSupply + (1 as UInt64)
299
300          return <- willoNft
301        }
302    }
303
304    access(all)
305    fun initMinter() {
306        if self.account.storage.type(at: self.MinterPublishedPath) == nil {
307            self.account.storage.save(<-create PublishedMinter(), to: self.MinterPublishedPath)
308        }
309    }
310
311    init() {
312        self.CollectionStoragePath = /storage/groundwork29Collection
313        self.CollectionPublicPath = /public/groundwork29Collection
314        self.MinterPublishedPath = /storage/minterGroundWork29Path
315
316        self.totalSupply = 0
317        self.libraryPassTotalSupply = 0
318        self.willoTotalSupply = 0
319
320        self.account.storage.save(<- create PublishedMinter(), to: self.MinterPublishedPath)
321
322        // Create a Collection resource and save it to storage
323        let collection <- create Collection()
324        self.account.storage.save(<-collection, to: self.CollectionStoragePath)
325
326        // create a public capability for the collection
327        let collectionCap = self.account.capabilities.storage.issue<&GroundWork29.Collection>(self.CollectionStoragePath)
328        self.account.capabilities.publish(collectionCap, at: self.CollectionPublicPath)
329
330        emit ContractInitialized()
331    }
332}