@zkpassport/sdk 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { randomBytes } from 'crypto'
2
- import { Alpha3Code, getAlpha3Code, registerLocale } from 'i18n-iso-countries'
1
+ import { randomBytes } from "crypto"
2
+ import { Alpha3Code, getAlpha3Code, registerLocale } from "i18n-iso-countries"
3
3
  import {
4
4
  type DisclosableIDCredential,
5
5
  type IDCredential,
@@ -30,27 +30,27 @@ import {
30
30
  DisclosedData,
31
31
  formatName,
32
32
  getHostedPackagedCircuitByName,
33
- } from '@zkpassport/utils'
34
- import { bytesToHex } from '@noble/ciphers/utils'
35
- import { getWebSocketClient, WebSocketClient } from './websocket'
36
- import { createEncryptedJsonRpcRequest } from './json-rpc'
37
- import { decrypt, generateECDHKeyPair, getSharedSecret } from './encryption'
38
- import logger from './logger'
39
- import { ungzip } from 'node-gzip'
33
+ } from "@zkpassport/utils"
34
+ import { bytesToHex } from "@noble/ciphers/utils"
35
+ import { getWebSocketClient, WebSocketClient } from "./websocket"
36
+ import { createEncryptedJsonRpcRequest } from "./json-rpc"
37
+ import { decrypt, generateECDHKeyPair, getSharedSecret } from "./encryption"
38
+ import { noLogger as logger } from "./logger"
39
+ import { ungzip } from "node-gzip"
40
40
  //import initNoirC from '@noir-lang/noirc_abi'
41
41
  //import initACVM from '@noir-lang/acvm_js'
42
42
 
43
- registerLocale(require('i18n-iso-countries/langs/en.json'))
43
+ registerLocale(require("i18n-iso-countries/langs/en.json"))
44
44
 
45
45
  function normalizeCountry(country: CountryName | Alpha3Code) {
46
46
  let normalizedCountry: Alpha3Code | undefined
47
- const alpha3 = getAlpha3Code(country, 'en') as Alpha3Code | undefined
47
+ const alpha3 = getAlpha3Code(country, "en") as Alpha3Code | undefined
48
48
  normalizedCountry = alpha3 || (country as Alpha3Code)
49
49
  return normalizedCountry
50
50
  }
51
51
 
52
52
  function numericalCompare(
53
- fnName: 'gte' | 'gt' | 'lte' | 'lt',
53
+ fnName: "gte" | "gt" | "lte" | "lt",
54
54
  key: NumericalIDCredential,
55
55
  value: number | Date,
56
56
  requestId: string,
@@ -75,7 +75,7 @@ function rangeCompare(
75
75
  }
76
76
 
77
77
  function generalCompare(
78
- fnName: 'in' | 'out' | 'eq',
78
+ fnName: "in" | "out" | "eq",
79
79
  key: IDCredential,
80
80
  value: any,
81
81
  requestId: string,
@@ -87,7 +87,7 @@ function generalCompare(
87
87
  }
88
88
  }
89
89
 
90
- export type * from '@zkpassport/utils'
90
+ export type * from "@zkpassport/utils"
91
91
  export {
92
92
  SANCTIONED_COUNTRIES,
93
93
  EU_COUNTRIES,
@@ -95,7 +95,7 @@ export {
95
95
  SCHENGEN_COUNTRIES,
96
96
  ASEAN_COUNTRIES,
97
97
  MERCOSUR_COUNTRIES,
98
- } from '@zkpassport/utils'
98
+ } from "@zkpassport/utils"
99
99
 
100
100
  export type QueryBuilderResult = {
101
101
  /**
@@ -184,13 +184,13 @@ export type QueryBuilder = {
184
184
  * @param key The attribute to compare.
185
185
  * @param value The value of the attribute you require.
186
186
  */
187
- lte: <T extends 'birthdate' | 'expiry_date'>(key: T, value: IDCredentialValue<T>) => QueryBuilder
187
+ lte: <T extends "birthdate" | "expiry_date">(key: T, value: IDCredentialValue<T>) => QueryBuilder
188
188
  /**
189
189
  * Requires this attribute to be less than the provided value.
190
190
  * @param key The attribute to compare.
191
191
  * @param value The value of the attribute you require.
192
192
  */
193
- lt: <T extends 'age'>(key: T, value: IDCredentialValue<T>) => QueryBuilder
193
+ lt: <T extends "age">(key: T, value: IDCredentialValue<T>) => QueryBuilder
194
194
  /**
195
195
  * Requires this attribute to be included in the provided range.
196
196
  * @param key The attribute to compare.
@@ -207,13 +207,13 @@ export type QueryBuilder = {
207
207
  * @param key The attribute to compare.
208
208
  * @param value The list of values to check inclusion against.
209
209
  */
210
- in: <T extends 'nationality'>(key: T, value: IDCredentialValue<T>[]) => QueryBuilder
210
+ in: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder
211
211
  /**
212
212
  * Requires this attribute to be excluded from the provided list.
213
213
  * @param key The attribute to compare.
214
214
  * @param value The list of values to check exclusion against.
215
215
  */
216
- out: <T extends 'nationality'>(key: T, value: IDCredentialValue<T>[]) => QueryBuilder
216
+ out: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder
217
217
  /**
218
218
  * Requires this attribute to be disclosed.
219
219
  * @param key The attribute to disclose.
@@ -261,8 +261,8 @@ export class ZKPassport {
261
261
  //private wasmVerifierInit: boolean = false
262
262
 
263
263
  constructor(_domain?: string) {
264
- if (!_domain && typeof window === 'undefined') {
265
- throw new Error('Domain argument is required in Node.js environment')
264
+ if (!_domain && typeof window === "undefined") {
265
+ throw new Error("Domain argument is required in Node.js environment")
266
266
  }
267
267
  this.domain = _domain || window.location.hostname
268
268
  }
@@ -284,17 +284,17 @@ export class ZKPassport {
284
284
  request: JsonRpcRequest,
285
285
  outerRequest: JsonRpcRequest,
286
286
  ) {
287
- logger.debug('Received encrypted message:', request)
288
- if (request.method === 'accept') {
287
+ logger.debug("Received encrypted message:", request)
288
+ if (request.method === "accept") {
289
289
  logger.debug(`User accepted the request and is generating a proof`)
290
290
  await Promise.all(this.onGeneratingProofCallbacks[topic].map((callback) => callback(topic)))
291
- } else if (request.method === 'reject') {
291
+ } else if (request.method === "reject") {
292
292
  logger.debug(`User rejected the request`)
293
293
  await Promise.all(this.onRejectCallbacks[topic].map((callback) => callback()))
294
- } else if (request.method === 'proof') {
294
+ } else if (request.method === "proof") {
295
295
  logger.debug(`User generated proof`)
296
296
  // Uncompress the proof and convert it to a hex string
297
- const bytesProof = Buffer.from(request.params.proof, 'base64')
297
+ const bytesProof = Buffer.from(request.params.proof, "base64")
298
298
  const uncompressedProof = await ungzip(bytesProof)
299
299
  // The gzip lib in the app compress the proof as ASCII
300
300
  // and since the app passes the proof as a hex string, we can
@@ -310,7 +310,7 @@ export class ZKPassport {
310
310
  await Promise.all(
311
311
  this.onProofGeneratedCallbacks[topic].map((callback) => callback(processedProof)),
312
312
  )
313
- } else if (request.method === 'done') {
313
+ } else if (request.method === "done") {
314
314
  logger.debug(`User sent the query result`)
315
315
  // Verify the proofs and extract the unique identifier (aka nullifier) and the verification result
316
316
  const { uniqueIdentifier, verified } = await this.verify(
@@ -327,7 +327,7 @@ export class ZKPassport {
327
327
  }),
328
328
  ),
329
329
  )
330
- } else if (request.method === 'error') {
330
+ } else if (request.method === "error") {
331
331
  await Promise.all(
332
332
  this.onErrorCallbacks[topic].map((callback) => callback(request.params.error)),
333
333
  )
@@ -337,26 +337,26 @@ export class ZKPassport {
337
337
  private getZkPassportRequest(topic: string): QueryBuilder {
338
338
  return {
339
339
  eq: <T extends IDCredential>(key: T, value: IDCredentialValue<T>) => {
340
- if (key === 'issuing_country' || key === 'nationality') {
340
+ if (key === "issuing_country" || key === "nationality") {
341
341
  value = normalizeCountry(value as CountryName) as IDCredentialValue<T>
342
342
  }
343
- generalCompare('eq', key, value, topic, this.topicToConfig)
343
+ generalCompare("eq", key, value, topic, this.topicToConfig)
344
344
  return this.getZkPassportRequest(topic)
345
345
  },
346
346
  gte: <T extends NumericalIDCredential>(key: T, value: IDCredentialValue<T>) => {
347
- numericalCompare('gte', key, value, topic, this.topicToConfig)
347
+ numericalCompare("gte", key, value, topic, this.topicToConfig)
348
348
  return this.getZkPassportRequest(topic)
349
349
  },
350
350
  /*gt: <T extends NumericalIDCredential>(key: T, value: IDCredentialValue<T>) => {
351
351
  numericalCompare('gt', key, value, topic, this.topicToConfig)
352
352
  return this.getZkPassportRequest(topic)
353
353
  },*/
354
- lte: <T extends 'birthdate' | 'expiry_date'>(key: T, value: IDCredentialValue<T>) => {
355
- numericalCompare('lte', key, value, topic, this.topicToConfig)
354
+ lte: <T extends "birthdate" | "expiry_date">(key: T, value: IDCredentialValue<T>) => {
355
+ numericalCompare("lte", key, value, topic, this.topicToConfig)
356
356
  return this.getZkPassportRequest(topic)
357
357
  },
358
- lt: <T extends 'age'>(key: T, value: IDCredentialValue<T>) => {
359
- numericalCompare('lt', key, value, topic, this.topicToConfig)
358
+ lt: <T extends "age">(key: T, value: IDCredentialValue<T>) => {
359
+ numericalCompare("lt", key, value, topic, this.topicToConfig)
360
360
  return this.getZkPassportRequest(topic)
361
361
  },
362
362
  range: <T extends NumericalIDCredential>(
@@ -367,14 +367,14 @@ export class ZKPassport {
367
367
  rangeCompare(key, [start, end], topic, this.topicToConfig)
368
368
  return this.getZkPassportRequest(topic)
369
369
  },
370
- in: <T extends 'nationality'>(key: T, value: IDCredentialValue<T>[]) => {
370
+ in: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => {
371
371
  value = value.map((v) => normalizeCountry(v as CountryName)) as IDCredentialValue<T>[]
372
- generalCompare('in', key, value, topic, this.topicToConfig)
372
+ generalCompare("in", key, value, topic, this.topicToConfig)
373
373
  return this.getZkPassportRequest(topic)
374
374
  },
375
- out: <T extends 'nationality'>(key: T, value: IDCredentialValue<T>[]) => {
375
+ out: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => {
376
376
  value = value.map((v) => normalizeCountry(v as CountryName)) as IDCredentialValue<T>[]
377
- generalCompare('out', key, value, topic, this.topicToConfig)
377
+ generalCompare("out", key, value, topic, this.topicToConfig)
378
378
  return this.getZkPassportRequest(topic)
379
379
  },
380
380
  disclose: (key: DisclosableIDCredential) => {
@@ -389,10 +389,10 @@ export class ZKPassport {
389
389
  },*/
390
390
  done: () => {
391
391
  const base64Config = Buffer.from(JSON.stringify(this.topicToConfig[topic])).toString(
392
- 'base64',
392
+ "base64",
393
393
  )
394
394
  const base64Service = Buffer.from(JSON.stringify(this.topicToService[topic])).toString(
395
- 'base64',
395
+ "base64",
396
396
  )
397
397
  const pubkey = bytesToHex(this.topicToKeyPair[topic].publicKey)
398
398
  return {
@@ -442,7 +442,7 @@ export class ZKPassport {
442
442
  topicOverride?: string
443
443
  keyPairOverride?: { privateKey: Uint8Array; publicKey: Uint8Array }
444
444
  }) {
445
- const topic = topicOverride || randomBytes(16).toString('hex')
445
+ const topic = topicOverride || randomBytes(16).toString("hex")
446
446
 
447
447
  const keyPair = keyPairOverride || (await generateECDHKeyPair())
448
448
  this.topicToKeyPair[topic] = {
@@ -465,16 +465,16 @@ export class ZKPassport {
465
465
  const wsClient = getWebSocketClient(`wss://bridge.zkpassport.id?topic=${topic}`, this.domain)
466
466
  this.topicToWebSocketClient[topic] = wsClient
467
467
  wsClient.onopen = async () => {
468
- logger.info('[frontend] WebSocket connection established')
468
+ logger.info("[frontend] WebSocket connection established")
469
469
  await Promise.all(this.onBridgeConnectCallbacks[topic].map((callback) => callback()))
470
470
  }
471
- wsClient.addEventListener('message', async (event: any) => {
472
- logger.debug('[frontend] Received message:', event.data)
471
+ wsClient.addEventListener("message", async (event: any) => {
472
+ logger.debug("[frontend] Received message:", event.data)
473
473
  try {
474
474
  const data: JsonRpcRequest = JSON.parse(event.data)
475
475
  // Handshake happens when the mobile app scans the QR code and connects to the bridge
476
- if (data.method === 'handshake') {
477
- logger.debug('[frontend] Received handshake:', event.data)
476
+ if (data.method === "handshake") {
477
+ logger.debug("[frontend] Received handshake:", event.data)
478
478
 
479
479
  this.topicToRequestReceived[topic] = true
480
480
  this.topicToSharedSecret[topic] = await getSharedSecret(
@@ -482,17 +482,17 @@ export class ZKPassport {
482
482
  data.params.pubkey,
483
483
  )
484
484
  logger.debug(
485
- '[frontend] Shared secret:',
486
- Buffer.from(this.topicToSharedSecret[topic]).toString('hex'),
485
+ "[frontend] Shared secret:",
486
+ Buffer.from(this.topicToSharedSecret[topic]).toString("hex"),
487
487
  )
488
488
 
489
489
  const encryptedMessage = await createEncryptedJsonRpcRequest(
490
- 'hello',
490
+ "hello",
491
491
  null,
492
492
  this.topicToSharedSecret[topic],
493
493
  topic,
494
494
  )
495
- logger.debug('[frontend] Sending encrypted message:', encryptedMessage)
495
+ logger.debug("[frontend] Sending encrypted message:", encryptedMessage)
496
496
  wsClient.send(JSON.stringify(encryptedMessage))
497
497
 
498
498
  await Promise.all(this.onRequestReceivedCallbacks[topic].map((callback) => callback()))
@@ -500,11 +500,11 @@ export class ZKPassport {
500
500
  }
501
501
 
502
502
  // Handle encrypted messages
503
- if (data.method === 'encryptedMessage') {
503
+ if (data.method === "encryptedMessage") {
504
504
  // Decode the payload from base64 to Uint8Array
505
505
  const payload = new Uint8Array(
506
506
  atob(data.params.payload)
507
- .split('')
507
+ .split("")
508
508
  .map((c) => c.charCodeAt(0)),
509
509
  )
510
510
  try {
@@ -513,16 +513,16 @@ export class ZKPassport {
513
513
  const decryptedJson: JsonRpcRequest = JSON.parse(decrypted)
514
514
  this.handleEncryptedMessage(topic, decryptedJson, data)
515
515
  } catch (error) {
516
- logger.error('[frontend] Error decrypting message:', error)
516
+ logger.error("[frontend] Error decrypting message:", error)
517
517
  }
518
518
  return
519
519
  }
520
520
  } catch (error) {
521
- logger.error('[frontend] Error:', error)
521
+ logger.error("[frontend] Error:", error)
522
522
  }
523
523
  })
524
524
  wsClient.onerror = (error: Event) => {
525
- logger.error('[frontend] WebSocket error:', error)
525
+ logger.error("[frontend] WebSocket error:", error)
526
526
  }
527
527
  return this.getZkPassportRequest(topic)
528
528
  }
@@ -533,7 +533,7 @@ export class ZKPassport {
533
533
  let isCorrect = true
534
534
  let uniqueIdentifier: string | undefined
535
535
  const expectedMerkleRoot = BigInt(
536
- '21301853597069384763054217328384418971999152625381818922211526730996340553696',
536
+ "21301853597069384763054217328384418971999152625381818922211526730996340553696",
537
537
  )
538
538
  const defaultDateValue = new Date(1111, 10, 11)
539
539
  const currentTime = new Date()
@@ -551,18 +551,18 @@ export class ZKPassport {
551
551
  // by their expected order: root signature check -> ID signature check -> integrity check -> disclosure
552
552
  const sortedProofs = proofs.sort((a, b) => {
553
553
  const proofOrder = [
554
- 'sig_check_dsc',
555
- 'sig_check_id_data',
556
- 'data_check_integrity',
557
- 'disclose_bytes',
558
- 'compare_age',
559
- 'compare_birthdate',
560
- 'compare_expiry',
561
- 'exclusion_check_country',
562
- 'inclusion_check_country',
554
+ "sig_check_dsc",
555
+ "sig_check_id_data",
556
+ "data_check_integrity",
557
+ "disclose_bytes",
558
+ "compare_age",
559
+ "compare_birthdate",
560
+ "compare_expiry",
561
+ "exclusion_check_country",
562
+ "inclusion_check_country",
563
563
  ]
564
564
  const getIndex = (proof: ProofResult) => {
565
- const name = proof.name || ''
565
+ const name = proof.name || ""
566
566
  return proofOrder.findIndex((p) => name.startsWith(p))
567
567
  }
568
568
  return getIndex(a) - getIndex(b)
@@ -570,28 +570,28 @@ export class ZKPassport {
570
570
 
571
571
  for (const proof of sortedProofs!) {
572
572
  const proofData = getProofData(proof.proof as string, true)
573
- if (proof.name?.startsWith('sig_check_dsc')) {
573
+ if (proof.name?.startsWith("sig_check_dsc")) {
574
574
  commitmentOut = getCommitmentFromDSCProof(proofData)
575
575
  const merkleRoot = getMerkleRootFromDSCProof(proofData)
576
576
  if (merkleRoot !== expectedMerkleRoot) {
577
- console.warn('The ID was signed by an unrecognized root certificate')
577
+ console.warn("The ID was signed by an unrecognized root certificate")
578
578
  isCorrect = false
579
579
  break
580
580
  }
581
- } else if (proof.name?.startsWith('sig_check_id_data')) {
581
+ } else if (proof.name?.startsWith("sig_check_id_data")) {
582
582
  commitmentIn = getCommitmentInFromIDDataProof(proofData)
583
583
  if (commitmentIn !== commitmentOut) {
584
584
  console.warn(
585
- 'Failed to check the link between the certificate signature and ID signature',
585
+ "Failed to check the link between the certificate signature and ID signature",
586
586
  )
587
587
  isCorrect = false
588
588
  break
589
589
  }
590
590
  commitmentOut = getCommitmentOutFromIDDataProof(proofData)
591
- } else if (proof.name?.startsWith('data_check_integrity')) {
591
+ } else if (proof.name?.startsWith("data_check_integrity")) {
592
592
  commitmentIn = getCommitmentInFromIntegrityProof(proofData)
593
593
  if (commitmentIn !== commitmentOut) {
594
- console.warn('Failed to check the link between the ID signature and the data signed')
594
+ console.warn("Failed to check the link between the ID signature and the data signed")
595
595
  isCorrect = false
596
596
  break
597
597
  }
@@ -603,23 +603,23 @@ export class ZKPassport {
603
603
  currentDate.getTime() !== today.getTime() &&
604
604
  currentDate.getTime() !== today.getTime() - 86400000
605
605
  ) {
606
- console.warn('Current date used to check the validity of the ID is too old')
606
+ console.warn("Current date used to check the validity of the ID is too old")
607
607
  isCorrect = false
608
608
  break
609
609
  }
610
- } else if (proof.name === 'disclose_bytes') {
610
+ } else if (proof.name === "disclose_bytes") {
611
611
  commitmentIn = getCommitmentInFromDisclosureProof(proofData)
612
612
  if (commitmentIn !== commitmentOut) {
613
613
  console.warn(
614
- 'Failed to check the link between the validity of the ID and the data to disclose',
614
+ "Failed to check the link between the validity of the ID and the data to disclose",
615
615
  )
616
616
  isCorrect = false
617
617
  break
618
618
  }
619
619
  // We can't be certain that the disclosed data is for a passport or an ID card
620
620
  // so we need to check both (unless the document type is revealed)
621
- const disclosedDataPassport = DisclosedData.fromBytesProof(proofData, 'passport')
622
- const disclosedDataIDCard = DisclosedData.fromBytesProof(proofData, 'id_card')
621
+ const disclosedDataPassport = DisclosedData.fromBytesProof(proofData, "passport")
622
+ const disclosedDataIDCard = DisclosedData.fromBytesProof(proofData, "id_card")
623
623
  if (queryResult.document_type) {
624
624
  // Document type is always at the same index in the disclosed data
625
625
  if (
@@ -627,12 +627,12 @@ export class ZKPassport {
627
627
  queryResult.document_type.eq.result &&
628
628
  queryResult.document_type.eq.expected !== disclosedDataPassport.documentType
629
629
  ) {
630
- console.warn('Document type does not match the expected document type')
630
+ console.warn("Document type does not match the expected document type")
631
631
  isCorrect = false
632
632
  break
633
633
  }
634
634
  if (queryResult.document_type.disclose?.result !== disclosedDataIDCard.documentType) {
635
- console.warn('Document type does not match the disclosed document type in query result')
635
+ console.warn("Document type does not match the disclosed document type in query result")
636
636
  isCorrect = false
637
637
  break
638
638
  }
@@ -646,7 +646,7 @@ export class ZKPassport {
646
646
  queryResult.birthdate.eq.expected.getTime() !== birthdatePassport.getTime() &&
647
647
  queryResult.birthdate.eq.expected.getTime() !== birthdateIDCard.getTime()
648
648
  ) {
649
- console.warn('Birthdate does not match the expected birthdate')
649
+ console.warn("Birthdate does not match the expected birthdate")
650
650
  isCorrect = false
651
651
  break
652
652
  }
@@ -655,7 +655,7 @@ export class ZKPassport {
655
655
  queryResult.birthdate.disclose.result.getTime() !== birthdatePassport.getTime() &&
656
656
  queryResult.birthdate.disclose.result.getTime() !== birthdateIDCard.getTime()
657
657
  ) {
658
- console.warn('Birthdate does not match the disclosed birthdate in query result')
658
+ console.warn("Birthdate does not match the disclosed birthdate in query result")
659
659
  isCorrect = false
660
660
  break
661
661
  }
@@ -669,7 +669,7 @@ export class ZKPassport {
669
669
  queryResult.expiry_date.eq.expected.getTime() !== expiryDatePassport.getTime() &&
670
670
  queryResult.expiry_date.eq.expected.getTime() !== expiryDateIDCard.getTime()
671
671
  ) {
672
- console.warn('Expiry date does not match the expected expiry date')
672
+ console.warn("Expiry date does not match the expected expiry date")
673
673
  isCorrect = false
674
674
  break
675
675
  }
@@ -678,7 +678,7 @@ export class ZKPassport {
678
678
  queryResult.expiry_date.disclose.result.getTime() !== expiryDatePassport.getTime() &&
679
679
  queryResult.expiry_date.disclose.result.getTime() !== expiryDateIDCard.getTime()
680
680
  ) {
681
- console.warn('Expiry date does not match the disclosed expiry date in query result')
681
+ console.warn("Expiry date does not match the disclosed expiry date in query result")
682
682
  isCorrect = false
683
683
  break
684
684
  }
@@ -692,7 +692,7 @@ export class ZKPassport {
692
692
  queryResult.nationality.eq.expected !== nationalityPassport &&
693
693
  queryResult.nationality.eq.expected !== nationalityIDCard
694
694
  ) {
695
- console.warn('Nationality does not match the expected nationality')
695
+ console.warn("Nationality does not match the expected nationality")
696
696
  isCorrect = false
697
697
  break
698
698
  }
@@ -701,7 +701,7 @@ export class ZKPassport {
701
701
  queryResult.nationality.disclose.result !== nationalityPassport &&
702
702
  queryResult.nationality.disclose.result !== nationalityIDCard
703
703
  ) {
704
- console.warn('Nationality does not match the disclosed nationality in query result')
704
+ console.warn("Nationality does not match the disclosed nationality in query result")
705
705
  isCorrect = false
706
706
  break
707
707
  }
@@ -715,7 +715,7 @@ export class ZKPassport {
715
715
  queryResult.document_number.eq.expected !== documentNumberPassport &&
716
716
  queryResult.document_number.eq.expected !== documentNumberIDCard
717
717
  ) {
718
- console.warn('Document number does not match the expected document number')
718
+ console.warn("Document number does not match the expected document number")
719
719
  isCorrect = false
720
720
  break
721
721
  }
@@ -725,7 +725,7 @@ export class ZKPassport {
725
725
  queryResult.document_number.disclose.result !== documentNumberIDCard
726
726
  ) {
727
727
  console.warn(
728
- 'Document number does not match the disclosed document number in query result',
728
+ "Document number does not match the disclosed document number in query result",
729
729
  )
730
730
  isCorrect = false
731
731
  break
@@ -740,7 +740,7 @@ export class ZKPassport {
740
740
  queryResult.gender.eq.expected !== genderPassport &&
741
741
  queryResult.gender.eq.expected !== genderIDCard
742
742
  ) {
743
- console.warn('Gender does not match the expected gender')
743
+ console.warn("Gender does not match the expected gender")
744
744
  isCorrect = false
745
745
  break
746
746
  }
@@ -749,7 +749,7 @@ export class ZKPassport {
749
749
  queryResult.gender.disclose.result !== genderPassport &&
750
750
  queryResult.gender.disclose.result !== genderIDCard
751
751
  ) {
752
- console.warn('Gender does not match the disclosed gender in query result')
752
+ console.warn("Gender does not match the disclosed gender in query result")
753
753
  isCorrect = false
754
754
  break
755
755
  }
@@ -763,7 +763,7 @@ export class ZKPassport {
763
763
  queryResult.issuing_country.eq.expected !== issuingCountryPassport &&
764
764
  queryResult.issuing_country.eq.expected !== issuingCountryIDCard
765
765
  ) {
766
- console.warn('Issuing country does not match the expected issuing country')
766
+ console.warn("Issuing country does not match the expected issuing country")
767
767
  isCorrect = false
768
768
  break
769
769
  }
@@ -773,7 +773,7 @@ export class ZKPassport {
773
773
  queryResult.issuing_country.disclose.result !== issuingCountryIDCard
774
774
  ) {
775
775
  console.warn(
776
- 'Issuing country does not match the disclosed issuing country in query result',
776
+ "Issuing country does not match the disclosed issuing country in query result",
777
777
  )
778
778
  isCorrect = false
779
779
  break
@@ -790,7 +790,7 @@ export class ZKPassport {
790
790
  formatName(queryResult.fullname.eq.expected).toLowerCase() !==
791
791
  fullnameIDCard.toLowerCase()
792
792
  ) {
793
- console.warn('Fullname does not match the expected fullname')
793
+ console.warn("Fullname does not match the expected fullname")
794
794
  isCorrect = false
795
795
  break
796
796
  }
@@ -801,7 +801,7 @@ export class ZKPassport {
801
801
  formatName(queryResult.fullname.disclose.result).toLowerCase() !==
802
802
  fullnameIDCard.toLowerCase()
803
803
  ) {
804
- console.warn('Fullname does not match the disclosed fullname in query result')
804
+ console.warn("Fullname does not match the disclosed fullname in query result")
805
805
  isCorrect = false
806
806
  break
807
807
  }
@@ -824,7 +824,7 @@ export class ZKPassport {
824
824
  formatName(queryResult.firstname.eq.expected).toLowerCase() !==
825
825
  firstnameIDCard.toLowerCase()
826
826
  ) {
827
- console.warn('Firstname does not match the expected firstname')
827
+ console.warn("Firstname does not match the expected firstname")
828
828
  isCorrect = false
829
829
  break
830
830
  }
@@ -835,7 +835,7 @@ export class ZKPassport {
835
835
  formatName(queryResult.firstname.disclose.result).toLowerCase() !==
836
836
  firstnameIDCard.toLowerCase()
837
837
  ) {
838
- console.warn('Firstname does not match the disclosed firstname in query result')
838
+ console.warn("Firstname does not match the disclosed firstname in query result")
839
839
  isCorrect = false
840
840
  break
841
841
  }
@@ -858,7 +858,7 @@ export class ZKPassport {
858
858
  formatName(queryResult.lastname.eq.expected).toLowerCase() !==
859
859
  lastnameIDCard.toLowerCase()
860
860
  ) {
861
- console.warn('Lastname does not match the expected lastname')
861
+ console.warn("Lastname does not match the expected lastname")
862
862
  isCorrect = false
863
863
  break
864
864
  }
@@ -869,17 +869,17 @@ export class ZKPassport {
869
869
  formatName(queryResult.lastname.disclose.result).toLowerCase() !==
870
870
  lastnameIDCard.toLowerCase()
871
871
  ) {
872
- console.warn('Lastname does not match the disclosed lastname in query result')
872
+ console.warn("Lastname does not match the disclosed lastname in query result")
873
873
  isCorrect = false
874
874
  break
875
875
  }
876
876
  }
877
877
  uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10)
878
- } else if (proof.name === 'compare_age') {
878
+ } else if (proof.name === "compare_age") {
879
879
  commitmentIn = getCommitmentInFromDisclosureProof(proofData)
880
880
  if (commitmentIn !== commitmentOut) {
881
881
  console.warn(
882
- 'Failed to check the link between the validity of the ID and the age derived from it',
882
+ "Failed to check the link between the validity of the ID and the age derived from it",
883
883
  )
884
884
  isCorrect = false
885
885
  break
@@ -892,7 +892,7 @@ export class ZKPassport {
892
892
  queryResult.age.gte.result &&
893
893
  minAge < (queryResult.age.gte.expected as number)
894
894
  ) {
895
- console.warn('Age is not greater than or equal to the expected age')
895
+ console.warn("Age is not greater than or equal to the expected age")
896
896
  isCorrect = false
897
897
  break
898
898
  }
@@ -901,7 +901,7 @@ export class ZKPassport {
901
901
  queryResult.age.lt.result &&
902
902
  maxAge >= (queryResult.age.lt.expected as number)
903
903
  ) {
904
- console.warn('Age is not less than the expected age')
904
+ console.warn("Age is not less than the expected age")
905
905
  isCorrect = false
906
906
  break
907
907
  }
@@ -911,18 +911,18 @@ export class ZKPassport {
911
911
  (minAge < (queryResult.age.range.expected[0] as number) ||
912
912
  maxAge >= (queryResult.age.range.expected[1] as number))
913
913
  ) {
914
- console.warn('Age is not in the expected range')
914
+ console.warn("Age is not in the expected range")
915
915
  isCorrect = false
916
916
  break
917
917
  }
918
918
  }
919
919
  if (!queryResult.age.lt && !queryResult.age.range && maxAge != 0) {
920
- console.warn('Maximum age should be equal to 0')
920
+ console.warn("Maximum age should be equal to 0")
921
921
  isCorrect = false
922
922
  break
923
923
  }
924
924
  if (!queryResult.age.gte && !queryResult.age.range && minAge != 0) {
925
- console.warn('Minimum age should be equal to 0')
925
+ console.warn("Minimum age should be equal to 0")
926
926
  isCorrect = false
927
927
  break
928
928
  }
@@ -931,12 +931,12 @@ export class ZKPassport {
931
931
  (queryResult.age.disclose.result !== minAge ||
932
932
  queryResult.age.disclose.result !== maxAge)
933
933
  ) {
934
- console.warn('Age does not match the disclosed age in query result')
934
+ console.warn("Age does not match the disclosed age in query result")
935
935
  isCorrect = false
936
936
  break
937
937
  }
938
938
  } else {
939
- console.warn('Age is not set in the query result')
939
+ console.warn("Age is not set in the query result")
940
940
  isCorrect = false
941
941
  break
942
942
  }
@@ -945,16 +945,16 @@ export class ZKPassport {
945
945
  currentDate.getTime() !== today.getTime() &&
946
946
  currentDate.getTime() !== today.getTime() - 86400000
947
947
  ) {
948
- console.warn('Current date in the proof is too old')
948
+ console.warn("Current date in the proof is too old")
949
949
  isCorrect = false
950
950
  break
951
951
  }
952
952
  uniqueIdentifier = getCommitmentInFromDisclosureProof(proofData).toString(10)
953
- } else if (proof.name === 'compare_birthdate') {
953
+ } else if (proof.name === "compare_birthdate") {
954
954
  commitmentIn = getCommitmentInFromDisclosureProof(proofData)
955
955
  if (commitmentIn !== commitmentOut) {
956
956
  console.warn(
957
- 'Failed to check the link between the validity of the ID and the birthdate derived from it',
957
+ "Failed to check the link between the validity of the ID and the birthdate derived from it",
958
958
  )
959
959
  isCorrect = false
960
960
  break
@@ -967,7 +967,7 @@ export class ZKPassport {
967
967
  queryResult.birthdate.gte.result &&
968
968
  minDate < queryResult.birthdate.gte.expected
969
969
  ) {
970
- console.warn('Birthdate is not greater than or equal to the expected birthdate')
970
+ console.warn("Birthdate is not greater than or equal to the expected birthdate")
971
971
  isCorrect = false
972
972
  break
973
973
  }
@@ -976,7 +976,7 @@ export class ZKPassport {
976
976
  queryResult.birthdate.lte.result &&
977
977
  maxDate > queryResult.birthdate.lte.expected
978
978
  ) {
979
- console.warn('Birthdate is not less than the expected birthdate')
979
+ console.warn("Birthdate is not less than the expected birthdate")
980
980
  isCorrect = false
981
981
  break
982
982
  }
@@ -986,7 +986,7 @@ export class ZKPassport {
986
986
  (minDate < queryResult.birthdate.range.expected[0] ||
987
987
  maxDate > queryResult.birthdate.range.expected[1])
988
988
  ) {
989
- console.warn('Birthdate is not in the expected range')
989
+ console.warn("Birthdate is not in the expected range")
990
990
  isCorrect = false
991
991
  break
992
992
  }
@@ -996,7 +996,7 @@ export class ZKPassport {
996
996
  !queryResult.birthdate.range &&
997
997
  maxDate.getTime() != defaultDateValue.getTime()
998
998
  ) {
999
- console.warn('Maximum birthdate should be equal to default date value')
999
+ console.warn("Maximum birthdate should be equal to default date value")
1000
1000
  isCorrect = false
1001
1001
  break
1002
1002
  }
@@ -1005,21 +1005,21 @@ export class ZKPassport {
1005
1005
  !queryResult.birthdate.range &&
1006
1006
  minDate.getTime() != defaultDateValue.getTime()
1007
1007
  ) {
1008
- console.warn('Minimum birthdate should be equal to default date value')
1008
+ console.warn("Minimum birthdate should be equal to default date value")
1009
1009
  isCorrect = false
1010
1010
  break
1011
1011
  }
1012
1012
  } else {
1013
- console.warn('Birthdate is not set in the query result')
1013
+ console.warn("Birthdate is not set in the query result")
1014
1014
  isCorrect = false
1015
1015
  break
1016
1016
  }
1017
1017
  uniqueIdentifier = getCommitmentInFromDisclosureProof(proofData).toString(10)
1018
- } else if (proof.name === 'compare_expiry') {
1018
+ } else if (proof.name === "compare_expiry") {
1019
1019
  commitmentIn = getCommitmentInFromDisclosureProof(proofData)
1020
1020
  if (commitmentIn !== commitmentOut) {
1021
1021
  console.warn(
1022
- 'Failed to check the link between the validity of the ID and its expiry date',
1022
+ "Failed to check the link between the validity of the ID and its expiry date",
1023
1023
  )
1024
1024
  isCorrect = false
1025
1025
  break
@@ -1032,7 +1032,7 @@ export class ZKPassport {
1032
1032
  queryResult.expiry_date.gte.result &&
1033
1033
  minDate < queryResult.expiry_date.gte.expected
1034
1034
  ) {
1035
- console.warn('Expiry date is not greater than or equal to the expected expiry date')
1035
+ console.warn("Expiry date is not greater than or equal to the expected expiry date")
1036
1036
  isCorrect = false
1037
1037
  break
1038
1038
  }
@@ -1041,7 +1041,7 @@ export class ZKPassport {
1041
1041
  queryResult.expiry_date.lte.result &&
1042
1042
  maxDate > queryResult.expiry_date.lte.expected
1043
1043
  ) {
1044
- console.warn('Expiry date is not less than the expected expiry date')
1044
+ console.warn("Expiry date is not less than the expected expiry date")
1045
1045
  isCorrect = false
1046
1046
  break
1047
1047
  }
@@ -1051,7 +1051,7 @@ export class ZKPassport {
1051
1051
  (minDate < queryResult.expiry_date.range.expected[0] ||
1052
1052
  maxDate > queryResult.expiry_date.range.expected[1])
1053
1053
  ) {
1054
- console.warn('Expiry date is not in the expected range')
1054
+ console.warn("Expiry date is not in the expected range")
1055
1055
  isCorrect = false
1056
1056
  break
1057
1057
  }
@@ -1061,7 +1061,7 @@ export class ZKPassport {
1061
1061
  !queryResult.expiry_date.range &&
1062
1062
  maxDate.getTime() != defaultDateValue.getTime()
1063
1063
  ) {
1064
- console.warn('Maximum expiry date should be equal to default date value')
1064
+ console.warn("Maximum expiry date should be equal to default date value")
1065
1065
  isCorrect = false
1066
1066
  break
1067
1067
  }
@@ -1070,21 +1070,21 @@ export class ZKPassport {
1070
1070
  !queryResult.expiry_date.range &&
1071
1071
  minDate.getTime() != defaultDateValue.getTime()
1072
1072
  ) {
1073
- console.warn('Minimum expiry date should be equal to default date value')
1073
+ console.warn("Minimum expiry date should be equal to default date value")
1074
1074
  isCorrect = false
1075
1075
  break
1076
1076
  }
1077
1077
  } else {
1078
- console.warn('Expiry date is not set in the query result')
1078
+ console.warn("Expiry date is not set in the query result")
1079
1079
  isCorrect = false
1080
1080
  break
1081
1081
  }
1082
1082
  uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10)
1083
- } else if (proof.name === 'exclusion_check_country') {
1083
+ } else if (proof.name === "exclusion_check_country") {
1084
1084
  commitmentIn = getCommitmentInFromDisclosureProof(proofData)
1085
1085
  if (commitmentIn !== commitmentOut) {
1086
1086
  console.warn(
1087
- 'Failed to check the link between the validity of the ID and the country exclusion check',
1087
+ "Failed to check the link between the validity of the ID and the country exclusion check",
1088
1088
  )
1089
1089
  isCorrect = false
1090
1090
  break
@@ -1098,21 +1098,21 @@ export class ZKPassport {
1098
1098
  if (
1099
1099
  !queryResult.nationality.out.expected?.every((country) => countryList.includes(country))
1100
1100
  ) {
1101
- console.warn('Country exclusion list does not match the one from the query results')
1101
+ console.warn("Country exclusion list does not match the one from the query results")
1102
1102
  isCorrect = false
1103
1103
  break
1104
1104
  }
1105
1105
  } else if (!queryResult.nationality || !queryResult.nationality.out) {
1106
- console.warn('Nationality exclusion is not set in the query result')
1106
+ console.warn("Nationality exclusion is not set in the query result")
1107
1107
  isCorrect = false
1108
1108
  break
1109
1109
  }
1110
1110
  uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10)
1111
- } else if (proof.name === 'inclusion_check_country') {
1111
+ } else if (proof.name === "inclusion_check_country") {
1112
1112
  commitmentIn = getCommitmentInFromDisclosureProof(proofData)
1113
1113
  if (commitmentIn !== commitmentOut) {
1114
1114
  console.warn(
1115
- 'Failed to check the link between the validity of the ID and the country inclusion check',
1115
+ "Failed to check the link between the validity of the ID and the country inclusion check",
1116
1116
  )
1117
1117
  isCorrect = false
1118
1118
  break
@@ -1126,12 +1126,12 @@ export class ZKPassport {
1126
1126
  if (
1127
1127
  !queryResult.nationality.in.expected?.every((country) => countryList.includes(country))
1128
1128
  ) {
1129
- console.warn('Country inclusion list does not match the one from the query results')
1129
+ console.warn("Country inclusion list does not match the one from the query results")
1130
1130
  isCorrect = false
1131
1131
  break
1132
1132
  }
1133
1133
  } else if (!queryResult.nationality || !queryResult.nationality.in) {
1134
- console.warn('Nationality inclusion is not set in the query result')
1134
+ console.warn("Nationality inclusion is not set in the query result")
1135
1135
  isCorrect = false
1136
1136
  break
1137
1137
  }
@@ -1155,13 +1155,17 @@ export class ZKPassport {
1155
1155
  queryResult?: QueryResult,
1156
1156
  ): Promise<{ uniqueIdentifier: string | undefined; verified: boolean }> {
1157
1157
  let proofsToVerify = proofs
1158
- if (!proofs) {
1158
+ // There is a minimum of 4 subproofs to make a complete proof
1159
+ if (!proofs || proofs.length < 4) {
1159
1160
  proofsToVerify = this.topicToProofs[requestId]
1160
- if (!proofsToVerify || proofsToVerify.length === 0) {
1161
- throw new Error('No proofs to verify')
1161
+ if (!proofsToVerify || proofsToVerify.length < 4) {
1162
+ // It may happen that a request returns a result without proofs
1163
+ // Meaning the ID is supported yet by ZKPassport circuits,
1164
+ // so the results has to be trusted and cannot be independently verified
1165
+ return { uniqueIdentifier: undefined, verified: false }
1162
1166
  }
1163
1167
  }
1164
- const { BarretenbergVerifier } = await import('@aztec/bb.js')
1168
+ const { BarretenbergVerifier } = await import("@aztec/bb.js")
1165
1169
  const verifier = new BarretenbergVerifier()
1166
1170
  /*if (!this.wasmVerifierInit) {
1167
1171
  await this.initWasmVerifier()
@@ -1182,11 +1186,11 @@ export class ZKPassport {
1182
1186
  proof.version as any,
1183
1187
  proof.name!,
1184
1188
  )
1185
- const vkeyBytes = Buffer.from(hostedPackagedCircuit.vkey, 'base64')
1189
+ const vkeyBytes = Buffer.from(hostedPackagedCircuit.vkey, "base64")
1186
1190
  try {
1187
1191
  verified = await verifier.verifyUltraHonkProof(proofData, new Uint8Array(vkeyBytes))
1188
1192
  } catch (e) {
1189
- console.warn('Error verifying proof', e)
1193
+ console.warn("Error verifying proof", e)
1190
1194
  verified = false
1191
1195
  }
1192
1196
  if (!verified) {
@@ -1208,10 +1212,10 @@ export class ZKPassport {
1208
1212
  public getUrl(requestId: string) {
1209
1213
  const pubkey = bytesToHex(this.topicToKeyPair[requestId].publicKey)
1210
1214
  const base64Config = Buffer.from(JSON.stringify(this.topicToConfig[requestId])).toString(
1211
- 'base64',
1215
+ "base64",
1212
1216
  )
1213
1217
  const base64Service = Buffer.from(JSON.stringify(this.topicToService[requestId])).toString(
1214
- 'base64',
1218
+ "base64",
1215
1219
  )
1216
1220
  return `https://zkpassport.id/r?d=${this.domain}&t=${requestId}&c=${base64Config}&s=${base64Service}&p=${pubkey}`
1217
1221
  }