@zkpassport/sdk 0.2.8 → 0.2.9

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/dist/cjs/index.js CHANGED
@@ -80,6 +80,7 @@ class ZKPassport {
80
80
  this.topicToService = {};
81
81
  this.topicToProofs = {};
82
82
  this.topicToExpectedProofCount = {};
83
+ this.topicToFailedProofCount = {};
83
84
  this.topicToResults = {};
84
85
  this.onRequestReceivedCallbacks = {};
85
86
  this.onGeneratingProofCallbacks = {};
@@ -104,14 +105,19 @@ class ZKPassport {
104
105
  // Clear the results straight away to avoid concurrency issues
105
106
  delete this.topicToResults[topic];
106
107
  // Verify the proofs and extract the unique identifier (aka nullifier) and the verification result
107
- const { uniqueIdentifier, verified } = await this.verify(topic, this.topicToProofs[topic], result);
108
+ const { uniqueIdentifier, verified, queryResultErrors } = await this.verify(topic, this.topicToProofs[topic], result);
109
+ const hasFailedProofs = this.topicToFailedProofCount[topic] > 0;
108
110
  await Promise.all(this.onResultCallbacks[topic].map((callback) => callback({
109
- uniqueIdentifier,
110
- verified,
111
+ // If there are failed proofs, we don't return the unique identifier
112
+ // and we set the verified result to false
113
+ uniqueIdentifier: hasFailedProofs ? undefined : uniqueIdentifier,
114
+ verified: hasFailedProofs ? false : verified,
111
115
  result,
116
+ queryResultErrors,
112
117
  })));
113
- // Clear the expected proof count
118
+ // Clear the expected proof count and failed proof count
114
119
  delete this.topicToExpectedProofCount[topic];
120
+ delete this.topicToFailedProofCount[topic];
115
121
  }
116
122
  setExpectedProofCount(topic) {
117
123
  const fields = Object.keys(this.topicToConfig[topic]).filter((key) => hasRequestedAccessToField(this.topicToConfig[topic], key));
@@ -162,6 +168,7 @@ class ZKPassport {
162
168
  // Each separate needed circuit adds 1 disclosure proof
163
169
  this.topicToExpectedProofCount[topic] =
164
170
  neededCircuits.length === 0 ? 4 : 3 + neededCircuits.length;
171
+ this.topicToFailedProofCount[topic] = 0;
165
172
  }
166
173
  /**
167
174
  * @notice Handle an encrypted message.
@@ -217,6 +224,7 @@ class ZKPassport {
217
224
  // This means the user has an ID that is not supported yet
218
225
  // So we won't receive any proofs and we can handle the result now
219
226
  this.topicToExpectedProofCount[topic] = 0;
227
+ this.topicToFailedProofCount[topic] += this.topicToExpectedProofCount[topic];
220
228
  if (this.topicToResults[topic]) {
221
229
  await this.handleResult(topic);
222
230
  }
@@ -225,6 +233,7 @@ class ZKPassport {
225
233
  // This means one of the disclosure proofs failed to be generated
226
234
  // So we need to remove one from the expected proof count
227
235
  this.topicToExpectedProofCount[topic] -= 1;
236
+ this.topicToFailedProofCount[topic] += 1;
228
237
  // If the expected proof count is now equal to the number of proofs received
229
238
  // and the results were received, we can handle the result now
230
239
  if (this.topicToResults[topic] &&
@@ -281,9 +290,6 @@ class ZKPassport {
281
290
  };
282
291
  return this.getZkPassportRequest(topic);
283
292
  },
284
- /*checkAML: (country?: CountryName | Alpha2Code | Alpha3Code) => {
285
- return this.getZkPassportRequest(topic)
286
- },*/
287
293
  done: () => {
288
294
  const base64Config = buffer_1.Buffer.from(JSON.stringify(this.topicToConfig[topic])).toString("base64");
289
295
  const base64Service = buffer_1.Buffer.from(JSON.stringify(this.topicToService[topic])).toString("base64");
@@ -394,6 +400,23 @@ class ZKPassport {
394
400
  const defaultDateValue = new Date(1111, 10, 11);
395
401
  const currentTime = new Date();
396
402
  const today = new Date(currentTime.getFullYear(), currentTime.getMonth(), currentTime.getDate(), 0, 0, 0, 0);
403
+ const queryResultErrors = {
404
+ sig_check_dsc: {},
405
+ sig_check_id_data: {},
406
+ data_check_integrity: {},
407
+ disclose: {},
408
+ age: {},
409
+ birthdate: {},
410
+ expiry_date: {},
411
+ document_type: {},
412
+ issuing_country: {},
413
+ gender: {},
414
+ nationality: {},
415
+ firstname: {},
416
+ lastname: {},
417
+ fullname: {},
418
+ document_number: {},
419
+ };
397
420
  // Since the order is important for the commitments, we need to sort the proofs
398
421
  // by their expected order: root signature check -> ID signature check -> integrity check -> disclosure
399
422
  const sortedProofs = proofs.sort((a, b) => {
@@ -422,7 +445,11 @@ class ZKPassport {
422
445
  if (merkleRoot !== expectedMerkleRoot) {
423
446
  console.warn("The ID was signed by an unrecognized root certificate");
424
447
  isCorrect = false;
425
- break;
448
+ queryResultErrors.sig_check_dsc.certificate = {
449
+ expected: `Certificate registry root: ${expectedMerkleRoot.toString()}`,
450
+ received: `Certificate registry root: ${merkleRoot.toString()}`,
451
+ message: "The ID was signed by an unrecognized root certificate",
452
+ };
426
453
  }
427
454
  }
428
455
  else if (proof.name?.startsWith("sig_check_id_data")) {
@@ -430,7 +457,11 @@ class ZKPassport {
430
457
  if (commitmentIn !== commitmentOut) {
431
458
  console.warn("Failed to check the link between the certificate signature and ID signature");
432
459
  isCorrect = false;
433
- break;
460
+ queryResultErrors.sig_check_id_data.commitment = {
461
+ expected: `Commitment: ${commitmentOut?.toString() || "undefined"}`,
462
+ received: `Commitment: ${commitmentIn?.toString() || "undefined"}`,
463
+ message: "Failed to check the link between the certificate signature and ID signature",
464
+ };
434
465
  }
435
466
  commitmentOut = (0, utils_1.getCommitmentOutFromIDDataProof)(proofData);
436
467
  }
@@ -439,7 +470,11 @@ class ZKPassport {
439
470
  if (commitmentIn !== commitmentOut) {
440
471
  console.warn("Failed to check the link between the ID signature and the data signed");
441
472
  isCorrect = false;
442
- break;
473
+ queryResultErrors.data_check_integrity.commitment = {
474
+ expected: `Commitment: ${commitmentOut?.toString() || "undefined"}`,
475
+ received: `Commitment: ${commitmentIn?.toString() || "undefined"}`,
476
+ message: "Failed to check the link between the ID signature and the data signed",
477
+ };
443
478
  }
444
479
  commitmentOut = (0, utils_1.getCommitmentOutFromIntegrityProof)(proofData);
445
480
  const currentDate = (0, utils_1.getCurrentDateFromIntegrityProof)(proofData);
@@ -450,7 +485,11 @@ class ZKPassport {
450
485
  if (todayToCurrentDate >= actualDifference) {
451
486
  console.warn(`The date used to check the validity of the ID is older than ${this.topicToLocalConfig[topic]?.validity} days. You can ask the user to rescan their ID or ask them to disclose their expiry date`);
452
487
  isCorrect = false;
453
- break;
488
+ queryResultErrors.data_check_integrity.date = {
489
+ expected: `Difference: ${this.topicToLocalConfig[topic]?.validity} days`,
490
+ received: `Difference: ${Math.round(todayToCurrentDate / 86400000)} days`,
491
+ message: "The date used to check the validity of the ID is older than the validity period",
492
+ };
454
493
  }
455
494
  }
456
495
  else if (proof.name === "disclose_bytes") {
@@ -458,7 +497,11 @@ class ZKPassport {
458
497
  if (commitmentIn !== commitmentOut) {
459
498
  console.warn("Failed to check the link between the validity of the ID and the data to disclose");
460
499
  isCorrect = false;
461
- break;
500
+ queryResultErrors.disclose.commitment = {
501
+ expected: `Commitment: ${commitmentOut?.toString() || "undefined"}`,
502
+ received: `Commitment: ${commitmentIn?.toString() || "undefined"}`,
503
+ message: "Failed to check the link between the validity of the ID and the data to disclose",
504
+ };
462
505
  }
463
506
  // We can't be certain that the disclosed data is for a passport or an ID card
464
507
  // so we need to check both (unless the document type is revealed)
@@ -471,12 +514,20 @@ class ZKPassport {
471
514
  queryResult.document_type.eq.expected !== disclosedDataPassport.documentType) {
472
515
  console.warn("Document type does not match the expected document type");
473
516
  isCorrect = false;
474
- break;
517
+ queryResultErrors.document_type.eq = {
518
+ expected: `${queryResult.document_type.eq.expected}`,
519
+ received: `${disclosedDataPassport.documentType}`,
520
+ message: "Document type does not match the expected document type",
521
+ };
475
522
  }
476
523
  if (queryResult.document_type.disclose?.result !== disclosedDataIDCard.documentType) {
477
524
  console.warn("Document type does not match the disclosed document type in query result");
478
525
  isCorrect = false;
479
- break;
526
+ queryResultErrors.document_type.disclose = {
527
+ expected: `${queryResult.document_type.disclose?.result}`,
528
+ received: `${disclosedDataIDCard.documentType}`,
529
+ message: "Document type does not match the disclosed document type in query result",
530
+ };
480
531
  }
481
532
  }
482
533
  if (queryResult.birthdate) {
@@ -488,14 +539,22 @@ class ZKPassport {
488
539
  queryResult.birthdate.eq.expected.getTime() !== birthdateIDCard.getTime()) {
489
540
  console.warn("Birthdate does not match the expected birthdate");
490
541
  isCorrect = false;
491
- break;
542
+ queryResultErrors.birthdate.eq = {
543
+ expected: `${queryResult.birthdate.eq.expected.toISOString()}`,
544
+ received: `${birthdatePassport.toISOString()}`,
545
+ message: "Birthdate does not match the expected birthdate",
546
+ };
492
547
  }
493
548
  if (queryResult.birthdate.disclose &&
494
549
  queryResult.birthdate.disclose.result.getTime() !== birthdatePassport.getTime() &&
495
550
  queryResult.birthdate.disclose.result.getTime() !== birthdateIDCard.getTime()) {
496
551
  console.warn("Birthdate does not match the disclosed birthdate in query result");
497
552
  isCorrect = false;
498
- break;
553
+ queryResultErrors.birthdate.disclose = {
554
+ expected: `${queryResult.birthdate.disclose.result.toISOString()}`,
555
+ received: `${birthdatePassport.toISOString()}`,
556
+ message: "Birthdate does not match the disclosed birthdate in query result",
557
+ };
499
558
  }
500
559
  }
501
560
  if (queryResult.expiry_date) {
@@ -507,14 +566,22 @@ class ZKPassport {
507
566
  queryResult.expiry_date.eq.expected.getTime() !== expiryDateIDCard.getTime()) {
508
567
  console.warn("Expiry date does not match the expected expiry date");
509
568
  isCorrect = false;
510
- break;
569
+ queryResultErrors.expiry_date.eq = {
570
+ expected: `${queryResult.expiry_date.eq.expected.toISOString()}`,
571
+ received: `${expiryDatePassport.toISOString()}`,
572
+ message: "Expiry date does not match the expected expiry date",
573
+ };
511
574
  }
512
575
  if (queryResult.expiry_date.disclose &&
513
576
  queryResult.expiry_date.disclose.result.getTime() !== expiryDatePassport.getTime() &&
514
577
  queryResult.expiry_date.disclose.result.getTime() !== expiryDateIDCard.getTime()) {
515
578
  console.warn("Expiry date does not match the disclosed expiry date in query result");
516
579
  isCorrect = false;
517
- break;
580
+ queryResultErrors.expiry_date.disclose = {
581
+ expected: `${queryResult.expiry_date.disclose.result.toISOString()}`,
582
+ received: `${expiryDatePassport.toISOString()}`,
583
+ message: "Expiry date does not match the disclosed expiry date in query result",
584
+ };
518
585
  }
519
586
  }
520
587
  if (queryResult.nationality) {
@@ -526,14 +593,22 @@ class ZKPassport {
526
593
  queryResult.nationality.eq.expected !== nationalityIDCard) {
527
594
  console.warn("Nationality does not match the expected nationality");
528
595
  isCorrect = false;
529
- break;
596
+ queryResultErrors.nationality.eq = {
597
+ expected: `${queryResult.nationality.eq.expected}`,
598
+ received: `${nationalityPassport}`,
599
+ message: "Nationality does not match the expected nationality",
600
+ };
530
601
  }
531
602
  if (queryResult.nationality.disclose &&
532
603
  queryResult.nationality.disclose.result !== nationalityPassport &&
533
604
  queryResult.nationality.disclose.result !== nationalityIDCard) {
534
605
  console.warn("Nationality does not match the disclosed nationality in query result");
535
606
  isCorrect = false;
536
- break;
607
+ queryResultErrors.nationality.disclose = {
608
+ expected: `${queryResult.nationality.disclose.result}`,
609
+ received: `${nationalityPassport}`,
610
+ message: "Nationality does not match the disclosed nationality in query result",
611
+ };
537
612
  }
538
613
  }
539
614
  if (queryResult.document_number) {
@@ -545,14 +620,22 @@ class ZKPassport {
545
620
  queryResult.document_number.eq.expected !== documentNumberIDCard) {
546
621
  console.warn("Document number does not match the expected document number");
547
622
  isCorrect = false;
548
- break;
623
+ queryResultErrors.document_number.eq = {
624
+ expected: `${queryResult.document_number.eq.expected}`,
625
+ received: `${documentNumberPassport}`,
626
+ message: "Document number does not match the expected document number",
627
+ };
549
628
  }
550
629
  if (queryResult.document_number.disclose &&
551
630
  queryResult.document_number.disclose.result !== documentNumberPassport &&
552
631
  queryResult.document_number.disclose.result !== documentNumberIDCard) {
553
632
  console.warn("Document number does not match the disclosed document number in query result");
554
633
  isCorrect = false;
555
- break;
634
+ queryResultErrors.document_number.disclose = {
635
+ expected: `${queryResult.document_number.disclose.result}`,
636
+ received: `${documentNumberPassport}`,
637
+ message: "Document number does not match the disclosed document number in query result",
638
+ };
556
639
  }
557
640
  }
558
641
  if (queryResult.gender) {
@@ -564,14 +647,22 @@ class ZKPassport {
564
647
  queryResult.gender.eq.expected !== genderIDCard) {
565
648
  console.warn("Gender does not match the expected gender");
566
649
  isCorrect = false;
567
- break;
650
+ queryResultErrors.gender.eq = {
651
+ expected: `${queryResult.gender.eq.expected}`,
652
+ received: `${genderPassport}`,
653
+ message: "Gender does not match the expected gender",
654
+ };
568
655
  }
569
656
  if (queryResult.gender.disclose &&
570
657
  queryResult.gender.disclose.result !== genderPassport &&
571
658
  queryResult.gender.disclose.result !== genderIDCard) {
572
659
  console.warn("Gender does not match the disclosed gender in query result");
573
660
  isCorrect = false;
574
- break;
661
+ queryResultErrors.gender.disclose = {
662
+ expected: `${queryResult.gender.disclose.result}`,
663
+ received: `${genderPassport}`,
664
+ message: "Gender does not match the disclosed gender in query result",
665
+ };
575
666
  }
576
667
  }
577
668
  if (queryResult.issuing_country) {
@@ -583,14 +674,22 @@ class ZKPassport {
583
674
  queryResult.issuing_country.eq.expected !== issuingCountryIDCard) {
584
675
  console.warn("Issuing country does not match the expected issuing country");
585
676
  isCorrect = false;
586
- break;
677
+ queryResultErrors.issuing_country.eq = {
678
+ expected: `${queryResult.issuing_country.eq.expected}`,
679
+ received: `${issuingCountryPassport}`,
680
+ message: "Issuing country does not match the expected issuing country",
681
+ };
587
682
  }
588
683
  if (queryResult.issuing_country.disclose &&
589
684
  queryResult.issuing_country.disclose.result !== issuingCountryPassport &&
590
685
  queryResult.issuing_country.disclose.result !== issuingCountryIDCard) {
591
686
  console.warn("Issuing country does not match the disclosed issuing country in query result");
592
687
  isCorrect = false;
593
- break;
688
+ queryResultErrors.issuing_country.disclose = {
689
+ expected: `${queryResult.issuing_country.disclose.result}`,
690
+ received: `${issuingCountryPassport}`,
691
+ message: "Issuing country does not match the disclosed issuing country in query result",
692
+ };
594
693
  }
595
694
  }
596
695
  if (queryResult.fullname) {
@@ -604,7 +703,11 @@ class ZKPassport {
604
703
  fullnameIDCard.toLowerCase()) {
605
704
  console.warn("Fullname does not match the expected fullname");
606
705
  isCorrect = false;
607
- break;
706
+ queryResultErrors.fullname.eq = {
707
+ expected: `${queryResult.fullname.eq.expected}`,
708
+ received: `${fullnamePassport}`,
709
+ message: "Fullname does not match the expected fullname",
710
+ };
608
711
  }
609
712
  if (queryResult.fullname.disclose &&
610
713
  (0, utils_1.formatName)(queryResult.fullname.disclose.result).toLowerCase() !==
@@ -613,7 +716,11 @@ class ZKPassport {
613
716
  fullnameIDCard.toLowerCase()) {
614
717
  console.warn("Fullname does not match the disclosed fullname in query result");
615
718
  isCorrect = false;
616
- break;
719
+ queryResultErrors.fullname.disclose = {
720
+ expected: `${queryResult.fullname.disclose.result}`,
721
+ received: `${fullnamePassport}`,
722
+ message: "Fullname does not match the disclosed fullname in query result",
723
+ };
617
724
  }
618
725
  }
619
726
  if (queryResult.firstname) {
@@ -632,7 +739,11 @@ class ZKPassport {
632
739
  firstnameIDCard.toLowerCase()) {
633
740
  console.warn("Firstname does not match the expected firstname");
634
741
  isCorrect = false;
635
- break;
742
+ queryResultErrors.firstname.eq = {
743
+ expected: `${queryResult.firstname.eq.expected}`,
744
+ received: `${firstnamePassport}`,
745
+ message: "Firstname does not match the expected firstname",
746
+ };
636
747
  }
637
748
  if (queryResult.firstname.disclose &&
638
749
  (0, utils_1.formatName)(queryResult.firstname.disclose.result).toLowerCase() !==
@@ -641,7 +752,11 @@ class ZKPassport {
641
752
  firstnameIDCard.toLowerCase()) {
642
753
  console.warn("Firstname does not match the disclosed firstname in query result");
643
754
  isCorrect = false;
644
- break;
755
+ queryResultErrors.firstname.disclose = {
756
+ expected: `${queryResult.firstname.disclose.result}`,
757
+ received: `${firstnamePassport}`,
758
+ message: "Firstname does not match the disclosed firstname in query result",
759
+ };
645
760
  }
646
761
  }
647
762
  if (queryResult.lastname) {
@@ -660,7 +775,11 @@ class ZKPassport {
660
775
  lastnameIDCard.toLowerCase()) {
661
776
  console.warn("Lastname does not match the expected lastname");
662
777
  isCorrect = false;
663
- break;
778
+ queryResultErrors.lastname.eq = {
779
+ expected: `${queryResult.lastname.eq.expected}`,
780
+ received: `${lastnamePassport}`,
781
+ message: "Lastname does not match the expected lastname",
782
+ };
664
783
  }
665
784
  if (queryResult.lastname.disclose &&
666
785
  (0, utils_1.formatName)(queryResult.lastname.disclose.result).toLowerCase() !==
@@ -669,7 +788,11 @@ class ZKPassport {
669
788
  lastnameIDCard.toLowerCase()) {
670
789
  console.warn("Lastname does not match the disclosed lastname in query result");
671
790
  isCorrect = false;
672
- break;
791
+ queryResultErrors.lastname.disclose = {
792
+ expected: `${queryResult.lastname.disclose.result}`,
793
+ received: `${lastnamePassport}`,
794
+ message: "Lastname does not match the disclosed lastname in query result",
795
+ };
673
796
  }
674
797
  }
675
798
  uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
@@ -679,7 +802,11 @@ class ZKPassport {
679
802
  if (commitmentIn !== commitmentOut) {
680
803
  console.warn("Failed to check the link between the validity of the ID and the age derived from it");
681
804
  isCorrect = false;
682
- break;
805
+ queryResultErrors.age.commitment = {
806
+ expected: `Commitment: ${commitmentOut}`,
807
+ received: `Commitment: ${commitmentIn}`,
808
+ message: "Failed to check the link between the validity of the ID and the age derived from it",
809
+ };
683
810
  }
684
811
  const minAge = (0, utils_1.getMinAgeFromProof)(proofData);
685
812
  const maxAge = (0, utils_1.getMaxAgeFromProof)(proofData);
@@ -689,14 +816,22 @@ class ZKPassport {
689
816
  minAge < queryResult.age.gte.expected) {
690
817
  console.warn("Age is not greater than or equal to the expected age");
691
818
  isCorrect = false;
692
- break;
819
+ queryResultErrors.age.gte = {
820
+ expected: queryResult.age.gte.expected,
821
+ received: minAge,
822
+ message: "Age is not greater than or equal to the expected age",
823
+ };
693
824
  }
694
825
  if (queryResult.age.lt &&
695
826
  queryResult.age.lt.result &&
696
827
  maxAge >= queryResult.age.lt.expected) {
697
828
  console.warn("Age is not less than the expected age");
698
829
  isCorrect = false;
699
- break;
830
+ queryResultErrors.age.lt = {
831
+ expected: queryResult.age.lt.expected,
832
+ received: maxAge,
833
+ message: "Age is not less than the expected age",
834
+ };
700
835
  }
701
836
  if (queryResult.age.range) {
702
837
  if (queryResult.age.range.result &&
@@ -704,38 +839,60 @@ class ZKPassport {
704
839
  maxAge >= queryResult.age.range.expected[1])) {
705
840
  console.warn("Age is not in the expected range");
706
841
  isCorrect = false;
707
- break;
842
+ queryResultErrors.age.range = {
843
+ expected: queryResult.age.range.expected,
844
+ received: [minAge, maxAge],
845
+ message: "Age is not in the expected range",
846
+ };
708
847
  }
709
848
  }
710
849
  if (!queryResult.age.lt && !queryResult.age.range && maxAge != 0) {
711
850
  console.warn("Maximum age should be equal to 0");
712
851
  isCorrect = false;
713
- break;
852
+ queryResultErrors.age.disclose = {
853
+ expected: 0,
854
+ received: maxAge,
855
+ message: "Maximum age should be equal to 0",
856
+ };
714
857
  }
715
858
  if (!queryResult.age.gte && !queryResult.age.range && minAge != 0) {
716
859
  console.warn("Minimum age should be equal to 0");
717
860
  isCorrect = false;
718
- break;
861
+ queryResultErrors.age.disclose = {
862
+ expected: 0,
863
+ received: minAge,
864
+ message: "Minimum age should be equal to 0",
865
+ };
719
866
  }
720
867
  if (queryResult.age.disclose &&
721
868
  (queryResult.age.disclose.result !== minAge ||
722
869
  queryResult.age.disclose.result !== maxAge)) {
723
870
  console.warn("Age does not match the disclosed age in query result");
724
871
  isCorrect = false;
725
- break;
872
+ queryResultErrors.age.disclose = {
873
+ expected: `${minAge}`,
874
+ received: `${queryResult.age.disclose.result}`,
875
+ message: "Age does not match the disclosed age in query result",
876
+ };
726
877
  }
727
878
  }
728
879
  else {
729
880
  console.warn("Age is not set in the query result");
730
881
  isCorrect = false;
731
- break;
882
+ queryResultErrors.age.disclose = {
883
+ message: "Age is not set in the query result",
884
+ };
732
885
  }
733
886
  const currentDate = (0, utils_1.getCurrentDateFromAgeProof)(proofData);
734
887
  if (currentDate.getTime() !== today.getTime() &&
735
888
  currentDate.getTime() !== today.getTime() - 86400000) {
736
889
  console.warn("Current date in the proof is too old");
737
890
  isCorrect = false;
738
- break;
891
+ queryResultErrors.age.disclose = {
892
+ expected: `${today.toISOString()}`,
893
+ received: `${currentDate.toISOString()}`,
894
+ message: "Current date in the proof is too old",
895
+ };
739
896
  }
740
897
  uniqueIdentifier = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData).toString(10);
741
898
  }
@@ -744,7 +901,11 @@ class ZKPassport {
744
901
  if (commitmentIn !== commitmentOut) {
745
902
  console.warn("Failed to check the link between the validity of the ID and the birthdate derived from it");
746
903
  isCorrect = false;
747
- break;
904
+ queryResultErrors.birthdate.commitment = {
905
+ expected: `Commitment: ${commitmentOut}`,
906
+ received: `Commitment: ${commitmentIn}`,
907
+ message: "Failed to check the link between the validity of the ID and the birthdate derived from it",
908
+ };
748
909
  }
749
910
  const minDate = (0, utils_1.getMinDateFromProof)(proofData);
750
911
  const maxDate = (0, utils_1.getMaxDateFromProof)(proofData);
@@ -754,14 +915,22 @@ class ZKPassport {
754
915
  minDate < queryResult.birthdate.gte.expected) {
755
916
  console.warn("Birthdate is not greater than or equal to the expected birthdate");
756
917
  isCorrect = false;
757
- break;
918
+ queryResultErrors.birthdate.gte = {
919
+ expected: queryResult.birthdate.gte.expected,
920
+ received: minDate,
921
+ message: "Birthdate is not greater than or equal to the expected birthdate",
922
+ };
758
923
  }
759
924
  if (queryResult.birthdate.lte &&
760
925
  queryResult.birthdate.lte.result &&
761
926
  maxDate > queryResult.birthdate.lte.expected) {
762
927
  console.warn("Birthdate is not less than the expected birthdate");
763
928
  isCorrect = false;
764
- break;
929
+ queryResultErrors.birthdate.lte = {
930
+ expected: queryResult.birthdate.lte.expected,
931
+ received: maxDate,
932
+ message: "Birthdate is not less than the expected birthdate",
933
+ };
765
934
  }
766
935
  if (queryResult.birthdate.range) {
767
936
  if (queryResult.birthdate.range.result &&
@@ -769,7 +938,11 @@ class ZKPassport {
769
938
  maxDate > queryResult.birthdate.range.expected[1])) {
770
939
  console.warn("Birthdate is not in the expected range");
771
940
  isCorrect = false;
772
- break;
941
+ queryResultErrors.birthdate.range = {
942
+ expected: queryResult.birthdate.range.expected,
943
+ received: [minDate, maxDate],
944
+ message: "Birthdate is not in the expected range",
945
+ };
773
946
  }
774
947
  }
775
948
  if (!queryResult.birthdate.lte &&
@@ -777,20 +950,30 @@ class ZKPassport {
777
950
  maxDate.getTime() != defaultDateValue.getTime()) {
778
951
  console.warn("Maximum birthdate should be equal to default date value");
779
952
  isCorrect = false;
780
- break;
953
+ queryResultErrors.birthdate.disclose = {
954
+ expected: `${defaultDateValue.toISOString()}`,
955
+ received: `${maxDate.toISOString()}`,
956
+ message: "Maximum birthdate should be equal to default date value",
957
+ };
781
958
  }
782
959
  if (!queryResult.birthdate.gte &&
783
960
  !queryResult.birthdate.range &&
784
961
  minDate.getTime() != defaultDateValue.getTime()) {
785
962
  console.warn("Minimum birthdate should be equal to default date value");
786
963
  isCorrect = false;
787
- break;
964
+ queryResultErrors.birthdate.disclose = {
965
+ expected: `${defaultDateValue.toISOString()}`,
966
+ received: `${minDate.toISOString()}`,
967
+ message: "Minimum birthdate should be equal to default date value",
968
+ };
788
969
  }
789
970
  }
790
971
  else {
791
972
  console.warn("Birthdate is not set in the query result");
792
973
  isCorrect = false;
793
- break;
974
+ queryResultErrors.birthdate.disclose = {
975
+ message: "Birthdate is not set in the query result",
976
+ };
794
977
  }
795
978
  uniqueIdentifier = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData).toString(10);
796
979
  }
@@ -799,7 +982,11 @@ class ZKPassport {
799
982
  if (commitmentIn !== commitmentOut) {
800
983
  console.warn("Failed to check the link between the validity of the ID and its expiry date");
801
984
  isCorrect = false;
802
- break;
985
+ queryResultErrors.expiry_date.commitment = {
986
+ expected: `Commitment: ${commitmentOut}`,
987
+ received: `Commitment: ${commitmentIn}`,
988
+ message: "Failed to check the link between the validity of the ID and its expiry date",
989
+ };
803
990
  }
804
991
  const minDate = (0, utils_1.getMinDateFromProof)(proofData);
805
992
  const maxDate = (0, utils_1.getMaxDateFromProof)(proofData);
@@ -809,14 +996,22 @@ class ZKPassport {
809
996
  minDate < queryResult.expiry_date.gte.expected) {
810
997
  console.warn("Expiry date is not greater than or equal to the expected expiry date");
811
998
  isCorrect = false;
812
- break;
999
+ queryResultErrors.expiry_date.gte = {
1000
+ expected: queryResult.expiry_date.gte.expected,
1001
+ received: minDate,
1002
+ message: "Expiry date is not greater than or equal to the expected expiry date",
1003
+ };
813
1004
  }
814
1005
  if (queryResult.expiry_date.lte &&
815
1006
  queryResult.expiry_date.lte.result &&
816
1007
  maxDate > queryResult.expiry_date.lte.expected) {
817
1008
  console.warn("Expiry date is not less than the expected expiry date");
818
1009
  isCorrect = false;
819
- break;
1010
+ queryResultErrors.expiry_date.lte = {
1011
+ expected: queryResult.expiry_date.lte.expected,
1012
+ received: maxDate,
1013
+ message: "Expiry date is not less than the expected expiry date",
1014
+ };
820
1015
  }
821
1016
  if (queryResult.expiry_date.range) {
822
1017
  if (queryResult.expiry_date.range.result &&
@@ -824,7 +1019,11 @@ class ZKPassport {
824
1019
  maxDate > queryResult.expiry_date.range.expected[1])) {
825
1020
  console.warn("Expiry date is not in the expected range");
826
1021
  isCorrect = false;
827
- break;
1022
+ queryResultErrors.expiry_date.range = {
1023
+ expected: queryResult.expiry_date.range.expected,
1024
+ received: [minDate, maxDate],
1025
+ message: "Expiry date is not in the expected range",
1026
+ };
828
1027
  }
829
1028
  }
830
1029
  if (!queryResult.expiry_date.lte &&
@@ -832,20 +1031,30 @@ class ZKPassport {
832
1031
  maxDate.getTime() != defaultDateValue.getTime()) {
833
1032
  console.warn("Maximum expiry date should be equal to default date value");
834
1033
  isCorrect = false;
835
- break;
1034
+ queryResultErrors.expiry_date.disclose = {
1035
+ expected: `${defaultDateValue.toISOString()}`,
1036
+ received: `${maxDate.toISOString()}`,
1037
+ message: "Maximum expiry date should be equal to default date value",
1038
+ };
836
1039
  }
837
1040
  if (!queryResult.expiry_date.gte &&
838
1041
  !queryResult.expiry_date.range &&
839
1042
  minDate.getTime() != defaultDateValue.getTime()) {
840
1043
  console.warn("Minimum expiry date should be equal to default date value");
841
1044
  isCorrect = false;
842
- break;
1045
+ queryResultErrors.expiry_date.disclose = {
1046
+ expected: `${defaultDateValue.toISOString()}`,
1047
+ received: `${minDate.toISOString()}`,
1048
+ message: "Minimum expiry date should be equal to default date value",
1049
+ };
843
1050
  }
844
1051
  }
845
1052
  else {
846
1053
  console.warn("Expiry date is not set in the query result");
847
1054
  isCorrect = false;
848
- break;
1055
+ queryResultErrors.expiry_date.disclose = {
1056
+ message: "Expiry date is not set in the query result",
1057
+ };
849
1058
  }
850
1059
  uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
851
1060
  }
@@ -854,7 +1063,11 @@ class ZKPassport {
854
1063
  if (commitmentIn !== commitmentOut) {
855
1064
  console.warn("Failed to check the link between the validity of the ID and the country exclusion check");
856
1065
  isCorrect = false;
857
- break;
1066
+ queryResultErrors.nationality.commitment = {
1067
+ expected: `Commitment: ${commitmentOut}`,
1068
+ received: `Commitment: ${commitmentIn}`,
1069
+ message: "Failed to check the link between the validity of the ID and the country exclusion check",
1070
+ };
858
1071
  }
859
1072
  const countryList = (0, utils_1.getCountryListFromExclusionProof)(proofData);
860
1073
  if (queryResult.nationality &&
@@ -863,13 +1076,19 @@ class ZKPassport {
863
1076
  if (!queryResult.nationality.out.expected?.every((country) => countryList.includes(country))) {
864
1077
  console.warn("Country exclusion list does not match the one from the query results");
865
1078
  isCorrect = false;
866
- break;
1079
+ queryResultErrors.nationality.out = {
1080
+ expected: queryResult.nationality.out.expected,
1081
+ received: countryList,
1082
+ message: "Country exclusion list does not match the one from the query results",
1083
+ };
867
1084
  }
868
1085
  }
869
1086
  else if (!queryResult.nationality || !queryResult.nationality.out) {
870
1087
  console.warn("Nationality exclusion is not set in the query result");
871
1088
  isCorrect = false;
872
- break;
1089
+ queryResultErrors.nationality.out = {
1090
+ message: "Nationality exclusion is not set in the query result",
1091
+ };
873
1092
  }
874
1093
  // Check the countryList is in ascending order
875
1094
  // If the prover doesn't use a sorted list then the proof cannot be trusted
@@ -878,7 +1097,9 @@ class ZKPassport {
878
1097
  if (countryList[i] < countryList[i - 1]) {
879
1098
  console.warn("The nationality exclusion list has not been sorted, and thus the proof cannot be trusted");
880
1099
  isCorrect = false;
881
- break;
1100
+ queryResultErrors.nationality.out = {
1101
+ message: "The nationality exclusion list has not been sorted, and thus the proof cannot be trusted",
1102
+ };
882
1103
  }
883
1104
  }
884
1105
  uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
@@ -888,7 +1109,11 @@ class ZKPassport {
888
1109
  if (commitmentIn !== commitmentOut) {
889
1110
  console.warn("Failed to check the link between the validity of the ID and the country inclusion check");
890
1111
  isCorrect = false;
891
- break;
1112
+ queryResultErrors.nationality.commitment = {
1113
+ expected: `Commitment: ${commitmentOut}`,
1114
+ received: `Commitment: ${commitmentIn}`,
1115
+ message: "Failed to check the link between the validity of the ID and the country inclusion check",
1116
+ };
892
1117
  }
893
1118
  const countryList = (0, utils_1.getCountryListFromInclusionProof)(proofData);
894
1119
  if (queryResult.nationality &&
@@ -897,18 +1122,24 @@ class ZKPassport {
897
1122
  if (!queryResult.nationality.in.expected?.every((country) => countryList.includes(country))) {
898
1123
  console.warn("Country inclusion list does not match the one from the query results");
899
1124
  isCorrect = false;
900
- break;
1125
+ queryResultErrors.nationality.in = {
1126
+ expected: queryResult.nationality.in.expected,
1127
+ received: countryList,
1128
+ message: "Country inclusion list does not match the one from the query results",
1129
+ };
901
1130
  }
902
1131
  }
903
1132
  else if (!queryResult.nationality || !queryResult.nationality.in) {
904
1133
  console.warn("Nationality inclusion is not set in the query result");
905
1134
  isCorrect = false;
906
- break;
1135
+ queryResultErrors.nationality.in = {
1136
+ message: "Nationality inclusion is not set in the query result",
1137
+ };
907
1138
  }
908
1139
  uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
909
1140
  }
910
1141
  }
911
- return { isCorrect, uniqueIdentifier };
1142
+ return { isCorrect, uniqueIdentifier, queryResultErrors };
912
1143
  }
913
1144
  /**
914
1145
  * @notice Verify the proofs received from the mobile app.
@@ -923,12 +1154,6 @@ class ZKPassport {
923
1154
  // There is a minimum of 4 subproofs to make a complete proof
924
1155
  if (!proofs || proofs.length < 4) {
925
1156
  proofsToVerify = this.topicToProofs[requestId];
926
- if (!proofsToVerify || proofsToVerify.length < 4) {
927
- // It may happen that a request returns a result without proofs
928
- // Meaning the ID is not supported yet by ZKPassport circuits,
929
- // so the results has to be trusted and cannot be independently verified
930
- return { uniqueIdentifier: undefined, verified: false };
931
- }
932
1157
  }
933
1158
  const { BarretenbergVerifier } = await Promise.resolve().then(() => tslib_1.__importStar(require("@aztec/bb.js")));
934
1159
  const verifier = new BarretenbergVerifier();
@@ -937,13 +1162,15 @@ class ZKPassport {
937
1162
  }*/
938
1163
  let verified = true;
939
1164
  let uniqueIdentifier;
1165
+ let queryResultErrors;
940
1166
  if (queryResult) {
941
- const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs } = await this.checkPublicInputs(proofsToVerify, queryResult, requestId);
1167
+ const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs, queryResultErrors: queryResultErrorsFromPublicInputs, } = await this.checkPublicInputs(proofsToVerify, queryResult, requestId);
942
1168
  uniqueIdentifier = uniqueIdentifierFromPublicInputs;
943
1169
  verified = isCorrect;
1170
+ queryResultErrors = isCorrect ? undefined : queryResultErrorsFromPublicInputs;
944
1171
  }
945
1172
  // Only proceed with the proof verification if the public inputs are correct
946
- if (verified) {
1173
+ if (verified && queryResult) {
947
1174
  for (const proof of proofsToVerify) {
948
1175
  const proofData = (0, utils_1.getProofData)(proof.proof, true);
949
1176
  const hostedPackagedCircuit = await (0, utils_1.getHostedPackagedCircuitByName)(proof.version, proof.name);
@@ -963,7 +1190,7 @@ class ZKPassport {
963
1190
  }
964
1191
  }
965
1192
  this.topicToProofs[requestId] = [];
966
- return { uniqueIdentifier, verified };
1193
+ return { uniqueIdentifier, verified, queryResultErrors };
967
1194
  }
968
1195
  /**
969
1196
  * @notice Returns the URL of the request.
@@ -981,14 +1208,17 @@ class ZKPassport {
981
1208
  * @param requestId The request ID.
982
1209
  */
983
1210
  cancelRequest(requestId) {
984
- this.topicToWebSocketClient[requestId].close();
985
- delete this.topicToWebSocketClient[requestId];
1211
+ if (this.topicToWebSocketClient[requestId]) {
1212
+ this.topicToWebSocketClient[requestId].close();
1213
+ delete this.topicToWebSocketClient[requestId];
1214
+ }
986
1215
  delete this.topicToKeyPair[requestId];
987
1216
  delete this.topicToConfig[requestId];
988
1217
  delete this.topicToLocalConfig[requestId];
989
1218
  delete this.topicToSharedSecret[requestId];
990
1219
  delete this.topicToProofs[requestId];
991
1220
  delete this.topicToExpectedProofCount[requestId];
1221
+ delete this.topicToFailedProofCount[requestId];
992
1222
  delete this.topicToResults[requestId];
993
1223
  this.onRequestReceivedCallbacks[requestId] = [];
994
1224
  this.onGeneratingProofCallbacks[requestId] = [];
@@ -997,5 +1227,13 @@ class ZKPassport {
997
1227
  this.onRejectCallbacks[requestId] = [];
998
1228
  this.onErrorCallbacks[requestId] = [];
999
1229
  }
1230
+ /**
1231
+ * @notice Clears all requests.
1232
+ */
1233
+ clearAllRequests() {
1234
+ for (const requestId in this.topicToWebSocketClient) {
1235
+ this.cancelRequest(requestId);
1236
+ }
1237
+ }
1000
1238
  }
1001
1239
  exports.ZKPassport = ZKPassport;