Smart Contract
ProvineerV1
A.6b7453f9da8f4af1.ProvineerV1
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}