Smart Contract

ProvineerV1

A.6b7453f9da8f4af1.ProvineerV1

Deployed

2w ago
Feb 11, 2026, 05:36:00 PM UTC

Dependents

19 imports
1import NonFungibleToken from 0x1d7e57aa55817448
2import MetadataViews from 0x1d7e57aa55817448
3import ViewResolver from 0x1d7e57aa55817448
4
5access(all) contract ProvineerV1: ViewResolver, NonFungibleToken {
6
7    access(all) var totalSupply: UInt64
8
9    access(all) let CollectionStoragePath: StoragePath
10    access(all) let CollectionPublicPath: PublicPath
11    access(all) let ProvineerV1AdminStoragePath: StoragePath
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 ProvineerV1Created(id: UInt64, name: String, version: String, description: String, signature: String)
17
18    access(all) entitlement Minter
19
20    access(all) resource NFT: NonFungibleToken.NFT {
21        access(all) let id: UInt64
22        access(all) let certificate_id: String
23        access(all) let name: String
24        access(all) let version: String
25        access(all) let description: String
26        access(all) let url: String
27        access(all) let thumbnail: String
28        access(all) let main_sha256: String
29        access(all) let proofs_sha256: String
30        access(all) let email_sha256: String
31        access(all) let email_salt: String
32        access(all) let signature: String
33
34        access(all) view fun getViews(): [Type] {
35            return [
36                Type<MetadataViews.NFTView>(),
37                Type<MetadataViews.Display>(),
38                Type<MetadataViews.NFTCollectionData>(),
39                Type<MetadataViews.NFTCollectionDisplay>(),
40                Type<MetadataViews.ExternalURL>(),
41                Type<MetadataViews.Traits>()
42            ]
43        }
44
45        access(all) fun resolveView(_ view: Type): AnyStruct? {
46            switch view {
47                case Type<MetadataViews.NFTView>():
48                    let viewResolver = &self as &{ViewResolver.Resolver}
49                    return MetadataViews.NFTView(
50                        id: self.id,
51                        uuid: self.uuid,
52                        display: MetadataViews.getDisplay(viewResolver),
53                        externalURL: MetadataViews.getExternalURL(viewResolver),
54                        collectionData: MetadataViews.getNFTCollectionData(viewResolver),
55                        collectionDisplay: MetadataViews.getNFTCollectionDisplay(viewResolver),
56                        royalties: MetadataViews.getRoyalties(viewResolver),
57                        traits: MetadataViews.getTraits(viewResolver)
58                    )
59                case Type<MetadataViews.Display>():
60                    return MetadataViews.Display(
61                        name: self.name,
62                        description: self.description,
63                        thumbnail: MetadataViews.HTTPFile(
64                            url: self.thumbnail
65                        )
66                    )
67                case Type<MetadataViews.ExternalURL>():
68                    return MetadataViews.ExternalURL("https://www.provineer.com/")
69                case Type<MetadataViews.NFTCollectionDisplay>():
70                    let mediaSquare = MetadataViews.Media(
71                        file: MetadataViews.HTTPFile(
72                            url: "https://global-uploads.webflow.com/60f008ba9757da0940af288e/62e77af588325131a9aa8e61_4BFJowii_400x400.jpeg"
73                        ),
74                        mediaType: "image/svg+xml"
75                    )
76                    let mediaBanner = MetadataViews.Media(
77                        file: MetadataViews.HTTPFile(
78                            url: "https://www.provineer.com/static/logo-full-dark@2x-0e8797bb751b2fcb15c6c1227ca7b3b6.png"
79                        ),
80                        mediaType: "image/svg+xml"
81                    )
82                    return MetadataViews.NFTCollectionDisplay(
83                        name: "Provineer",
84                        description: "Authenticate anything, anytime, anywhere.",
85                        externalURL: MetadataViews.ExternalURL("https://www.provineer.com/"),
86                        squareImage: mediaSquare,
87                        bannerImage: mediaBanner,
88                        socials: {
89                            "twitter": MetadataViews.ExternalURL("https://twitter.com/provineer")
90                        }
91                    )
92                case Type<MetadataViews.NFTCollectionData>():
93                    return MetadataViews.NFTCollectionData(
94                        storagePath: ProvineerV1.CollectionStoragePath,
95                        publicPath: ProvineerV1.CollectionPublicPath,
96                        publicCollection: Type<&ProvineerV1.Collection>(),
97                        publicLinkedType: Type<&ProvineerV1.Collection>(),
98                        createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} { return <-ProvineerV1.createEmptyCollection(nftType: Type<@NFT>()) })
99                    )
100                    case Type<MetadataViews.Traits>():
101                    let traits: [MetadataViews.Trait] = []
102                        traits.append(MetadataViews.Trait(
103                            name: "File Version",
104                            value: self.version,
105                            displayType: nil,
106                            rarity: nil
107                        ))
108                    return MetadataViews.Traits(traits)
109            }
110
111            return nil
112        }
113
114        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
115            return <- ProvineerV1.createEmptyCollection(nftType: Type<@NFT>())
116        }
117
118        init(
119            certificate_id: String,
120            name: String,
121            version: String,
122            description: String,
123            url: String,
124            thumbnail: String,
125            main_sha256: String,
126            proofs_sha256: String,
127            email_sha256: String,
128            email_salt: String,
129            signature: String,
130        ) { 
131            self.id = self.uuid
132            self.certificate_id = certificate_id
133            self.name = name
134            self.version = version
135            self.description = description
136            self.url = url
137            self.thumbnail = thumbnail
138            self.main_sha256 = main_sha256
139            self.proofs_sha256 = proofs_sha256
140            self.email_sha256 = email_sha256
141            self.email_salt = email_salt
142            self.signature = signature
143        }
144    }
145
146    access(all) resource interface ProvineerV1CollectionPublic {
147        access(all) fun deposit(token: @{NonFungibleToken.NFT})
148        access(all) view fun getIDs(): [UInt64]
149        access(all) view fun borrowProvineerV1(id: UInt64): &ProvineerV1.NFT? { 
150            post {
151                (result == nil) || (result?.id == id): 
152                    "Cannot borrow Provineer reference: The ID of the returned reference is incorrect"
153            }
154        }      
155    }
156
157    access(all) resource Collection: NonFungibleToken.Collection, ProvineerV1CollectionPublic {
158        
159        access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
160
161        access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
162            let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
163
164            emit Withdraw(id: token.id, from: self.owner?.address)
165
166            return <-token
167        }
168
169        access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
170            let token <- token as! @ProvineerV1.NFT
171
172            let id: UInt64 = token.id
173
174            let oldToken <- self.ownedNFTs[id] <- token
175
176            emit Deposit(id: id, to: self.owner?.address)
177
178            destroy oldToken
179        }
180
181        access(all) view fun getIDs(): [UInt64] {
182            return self.ownedNFTs.keys
183        }
184
185        access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
186            return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
187        }
188
189        access(all) view fun borrowProvineerV1(id: UInt64): &ProvineerV1.NFT? {
190            if self.ownedNFTs[id] != nil {
191                let ref = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
192                return ref as! &ProvineerV1.NFT
193            }
194
195            return nil
196        }
197
198        access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver} {
199            let nft = (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)!
200            return nft
201        }
202
203        access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
204            return {
205                Type<@ProvineerV1.NFT>(): true
206            }
207        }
208
209        access(all) view fun isSupportedNFTType(type: Type): Bool {
210            return type == Type<@ProvineerV1.NFT>()
211        }
212
213        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
214            return <- create Collection()
215        }
216
217        init () {
218            self.ownedNFTs <- {}
219        }
220    }
221
222    access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
223        pre {
224            nftType == Type<@NFT>(): "incorrect nft type given"
225        }
226
227        return <- create Collection()
228    }
229
230    access(all) resource ProvineerV1Admin {
231
232        access(Minter) fun mintNFT(
233            recipient: &{NonFungibleToken.CollectionPublic},
234            certificate_id: String,
235            name: String,
236            version: String,
237            description: String,
238            url: String,
239            thumbnail: String,
240            main_sha256: String,
241            proofs_sha256: String,
242            email_sha256: String,
243            email_salt: String,
244            signature: String,
245        ) 
246        {  
247
248            recipient.deposit(token: <-create ProvineerV1.NFT(
249                                                certificate_id: certificate_id,
250                                                name: name,
251                                                version: version,
252                                                description: description,
253                                                url: url,
254                                                thumbnail: thumbnail,
255                                                main_sha256: main_sha256,
256                                                proofs_sha256: proofs_sha256,
257                                                email_sha256: email_sha256,
258                                                email_salt: email_salt,
259                                                signature: signature))
260
261
262            emit ProvineerV1Created(
263                id: self.uuid,
264                name: name,
265                version: version,
266                description: description,
267                signature: signature,
268            )
269
270            ProvineerV1.totalSupply = ProvineerV1.totalSupply + (1 as UInt64)
271        }
272    }
273
274    access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
275        switch viewType {
276            case Type<MetadataViews.NFTCollectionData>():
277                return MetadataViews.NFTCollectionData(
278                        storagePath: ProvineerV1.CollectionStoragePath,
279                        publicPath: ProvineerV1.CollectionPublicPath,
280                        publicCollection: Type<&ProvineerV1.Collection>(),
281                        publicLinkedType: Type<&ProvineerV1.Collection>(),
282                        createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} {
283                            return <-ProvineerV1.createEmptyCollection(nftType: Type<@NFT>())
284                        })
285                )
286            case Type<MetadataViews.NFTCollectionDisplay>():
287                    let mediaSquare = MetadataViews.Media(
288                        file: MetadataViews.HTTPFile(
289                            url: "https://global-uploads.webflow.com/60f008ba9757da0940af288e/62e77af588325131a9aa8e61_4BFJowii_400x400.jpeg"
290                        ),
291                        mediaType: "image/svg+xml"
292                    )
293                    let mediaBanner = MetadataViews.Media(
294                        file: MetadataViews.HTTPFile(
295                            url: "https://www.provineer.com/static/logo-full-dark@2x-0e8797bb751b2fcb15c6c1227ca7b3b6.png"
296                        ),
297                        mediaType: "image/svg+xml"
298                    )
299                return MetadataViews.NFTCollectionDisplay(
300                        name: "Provineer",
301                        description: "Authenticate anything, anytime, anywhere.",
302                        externalURL: MetadataViews.ExternalURL("https://www.provineer.com/"),
303                        squareImage: mediaSquare,
304                        bannerImage: mediaBanner,
305                        socials: {
306                            "twitter": MetadataViews.ExternalURL("https://twitter.com/provineer")
307                        }
308                    )
309        }
310        return nil
311    }
312
313    access(all) view fun getContractViews(resourceType: Type?): [Type] {
314        return [
315            Type<MetadataViews.NFTCollectionData>(),
316            Type<MetadataViews.NFTCollectionDisplay>(),
317            Type<MetadataViews.ExternalURL>()
318        ]
319    }
320
321    init() {
322        self.totalSupply = 0
323
324        self.CollectionStoragePath = /storage/provineerV1Collection
325        self.CollectionPublicPath = /public/provineerV1Collection
326        self.ProvineerV1AdminStoragePath = /storage/provineerV1Admin
327
328        let collection <- create Collection()
329        self.account.storage.save(<-collection, to: self.CollectionStoragePath)
330
331        let capability = self.account.capabilities.storage.issue<&ProvineerV1.Collection>(self.CollectionStoragePath)
332        self.account.capabilities.publish(capability, at: self.CollectionPublicPath)
333
334        let minter <- create ProvineerV1Admin()
335        self.account.storage.save(<-minter, to: self.ProvineerV1AdminStoragePath)
336
337        emit ContractInitialized()
338    }
339}