@zkpassport/sdk 0.2.9 → 0.2.11

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.
@@ -125,13 +125,13 @@ export type QueryBuilder = {
125
125
  * @param key The attribute to compare.
126
126
  * @param value The list of values to check inclusion against.
127
127
  */
128
- in: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder;
128
+ in: <T extends "nationality" | "issuing_country">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder;
129
129
  /**
130
130
  * Requires this attribute to be excluded from the provided list.
131
131
  * @param key The attribute to compare.
132
132
  * @param value The list of values to check exclusion against.
133
133
  */
134
- out: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder;
134
+ out: <T extends "nationality" | "issuing_country">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder;
135
135
  /**
136
136
  * Requires this attribute to be disclosed.
137
137
  * @param key The attribute to disclose.
@@ -200,13 +200,17 @@ export declare class ZKPassport {
200
200
  private checkPublicInputs;
201
201
  /**
202
202
  * @notice Verify the proofs received from the mobile app.
203
- * @param requestId The request ID.
204
203
  * @param proofs The proofs to verify.
205
204
  * @param queryResult The query result to verify against
205
+ * @param validity How many days ago should have the ID been last scanned by the user?
206
206
  * @returns An object containing the unique identifier associated to the user
207
207
  * and a boolean indicating whether the proofs were successfully verified.
208
208
  */
209
- verify(requestId: string, proofs?: Array<ProofResult>, queryResult?: QueryResult): Promise<{
209
+ verify({ proofs, queryResult, validity, }: {
210
+ proofs: Array<ProofResult>;
211
+ queryResult: QueryResult;
212
+ validity?: number;
213
+ }): Promise<{
210
214
  uniqueIdentifier: string | undefined;
211
215
  verified: boolean;
212
216
  queryResultErrors?: QueryResultErrors;
package/dist/cjs/index.js CHANGED
@@ -11,8 +11,6 @@ const json_rpc_1 = require("./json-rpc");
11
11
  const encryption_1 = require("./encryption");
12
12
  const logger_1 = require("./logger");
13
13
  const pako_1 = require("pako");
14
- //import initNoirC from '@noir-lang/noirc_abi'
15
- //import initACVM from '@noir-lang/acvm_js'
16
14
  const en_json_1 = tslib_1.__importDefault(require("i18n-iso-countries/langs/en.json"));
17
15
  const buffer_1 = require("buffer/");
18
16
  // If Buffer is not defined, then we use the Buffer from the buffer package
@@ -94,18 +92,17 @@ class ZKPassport {
94
92
  }
95
93
  this.domain = _domain || window.location.hostname;
96
94
  }
97
- /*private async initWasmVerifier() {
98
- const acvm = await import('@noir-lang/acvm_js/web/acvm_js_bg.wasm')
99
- const noirc = await import('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm')
100
- await Promise.all([initACVM(acvm), initNoirC(noirc)])
101
- this.wasmVerifierInit = true
102
- }*/
103
95
  async handleResult(topic) {
104
96
  const result = this.topicToResults[topic];
105
97
  // Clear the results straight away to avoid concurrency issues
106
98
  delete this.topicToResults[topic];
107
99
  // Verify the proofs and extract the unique identifier (aka nullifier) and the verification result
108
- const { uniqueIdentifier, verified, queryResultErrors } = await this.verify(topic, this.topicToProofs[topic], result);
100
+ const { uniqueIdentifier, verified, queryResultErrors } = await this.verify({
101
+ proofs: this.topicToProofs[topic],
102
+ queryResult: result,
103
+ validity: this.topicToLocalConfig[topic]?.validity,
104
+ });
105
+ delete this.topicToProofs[topic];
109
106
  const hasFailedProofs = this.topicToFailedProofCount[topic] > 0;
110
107
  await Promise.all(this.onResultCallbacks[topic].map((callback) => callback({
111
108
  // If there are failed proofs, we don't return the unique identifier
@@ -151,13 +148,23 @@ class ZKPassport {
151
148
  }
152
149
  break;
153
150
  case "in":
154
- if (field === "nationality" && !neededCircuits.includes("inclusion_check_country")) {
155
- neededCircuits.push("inclusion_check_country");
151
+ if (field === "nationality" &&
152
+ !neededCircuits.includes("inclusion_check_nationality")) {
153
+ neededCircuits.push("inclusion_check_nationality");
154
+ }
155
+ else if (field === "issuing_country" &&
156
+ !neededCircuits.includes("inclusion_check_issuing_country")) {
157
+ neededCircuits.push("inclusion_check_issuing_country");
156
158
  }
157
159
  break;
158
160
  case "out":
159
- if (field === "nationality" && !neededCircuits.includes("exclusion_check_country")) {
160
- neededCircuits.push("exclusion_check_country");
161
+ if (field === "nationality" &&
162
+ !neededCircuits.includes("exclusion_check_nationality")) {
163
+ neededCircuits.push("exclusion_check_nationality");
164
+ }
165
+ else if (field === "issuing_country" &&
166
+ !neededCircuits.includes("exclusion_check_issuing_country")) {
167
+ neededCircuits.push("exclusion_check_issuing_country");
161
168
  }
162
169
  break;
163
170
  }
@@ -391,7 +398,7 @@ class ZKPassport {
391
398
  };
392
399
  return this.getZkPassportRequest(topic);
393
400
  }
394
- async checkPublicInputs(proofs, queryResult, topic) {
401
+ async checkPublicInputs(proofs, queryResult, validity) {
395
402
  let commitmentIn;
396
403
  let commitmentOut;
397
404
  let isCorrect = true;
@@ -428,8 +435,10 @@ class ZKPassport {
428
435
  "compare_age",
429
436
  "compare_birthdate",
430
437
  "compare_expiry",
431
- "exclusion_check_country",
432
- "inclusion_check_country",
438
+ "exclusion_check_nationality",
439
+ "inclusion_check_nationality",
440
+ "exclusion_check_issuing_country",
441
+ "inclusion_check_issuing_country",
433
442
  ];
434
443
  const getIndex = (proof) => {
435
444
  const name = proof.name || "";
@@ -479,14 +488,15 @@ class ZKPassport {
479
488
  commitmentOut = (0, utils_1.getCommitmentOutFromIntegrityProof)(proofData);
480
489
  const currentDate = (0, utils_1.getCurrentDateFromIntegrityProof)(proofData);
481
490
  const todayToCurrentDate = today.getTime() - currentDate.getTime();
482
- const expectedDifference = this.topicToLocalConfig[topic]?.validity * 86400000;
491
+ const differenceInDays = validity ?? 180;
492
+ const expectedDifference = differenceInDays * 86400000;
483
493
  const actualDifference = today.getTime() - (today.getTime() - expectedDifference);
484
494
  // The ID should not expire within the next 6 months (or whatever the custom value is)
485
495
  if (todayToCurrentDate >= actualDifference) {
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`);
496
+ console.warn(`The date used to check the validity of the ID is older than ${differenceInDays} days. You can ask the user to rescan their ID or ask them to disclose their expiry date`);
487
497
  isCorrect = false;
488
498
  queryResultErrors.data_check_integrity.date = {
489
- expected: `Difference: ${this.topicToLocalConfig[topic]?.validity} days`,
499
+ expected: `Difference: ${differenceInDays} days`,
490
500
  received: `Difference: ${Math.round(todayToCurrentDate / 86400000)} days`,
491
501
  message: "The date used to check the validity of the ID is older than the validity period",
492
502
  };
@@ -516,7 +526,7 @@ class ZKPassport {
516
526
  isCorrect = false;
517
527
  queryResultErrors.document_type.eq = {
518
528
  expected: `${queryResult.document_type.eq.expected}`,
519
- received: `${disclosedDataPassport.documentType}`,
529
+ received: `${disclosedDataPassport.documentType ?? disclosedDataIDCard.documentType}`,
520
530
  message: "Document type does not match the expected document type",
521
531
  };
522
532
  }
@@ -525,7 +535,7 @@ class ZKPassport {
525
535
  isCorrect = false;
526
536
  queryResultErrors.document_type.disclose = {
527
537
  expected: `${queryResult.document_type.disclose?.result}`,
528
- received: `${disclosedDataIDCard.documentType}`,
538
+ received: `${disclosedDataIDCard.documentType ?? disclosedDataPassport.documentType}`,
529
539
  message: "Document type does not match the disclosed document type in query result",
530
540
  };
531
541
  }
@@ -541,7 +551,7 @@ class ZKPassport {
541
551
  isCorrect = false;
542
552
  queryResultErrors.birthdate.eq = {
543
553
  expected: `${queryResult.birthdate.eq.expected.toISOString()}`,
544
- received: `${birthdatePassport.toISOString()}`,
554
+ received: `${birthdatePassport?.toISOString() ?? birthdateIDCard?.toISOString()}`,
545
555
  message: "Birthdate does not match the expected birthdate",
546
556
  };
547
557
  }
@@ -552,7 +562,7 @@ class ZKPassport {
552
562
  isCorrect = false;
553
563
  queryResultErrors.birthdate.disclose = {
554
564
  expected: `${queryResult.birthdate.disclose.result.toISOString()}`,
555
- received: `${birthdatePassport.toISOString()}`,
565
+ received: `${birthdatePassport?.toISOString() ?? birthdateIDCard?.toISOString()}`,
556
566
  message: "Birthdate does not match the disclosed birthdate in query result",
557
567
  };
558
568
  }
@@ -568,7 +578,7 @@ class ZKPassport {
568
578
  isCorrect = false;
569
579
  queryResultErrors.expiry_date.eq = {
570
580
  expected: `${queryResult.expiry_date.eq.expected.toISOString()}`,
571
- received: `${expiryDatePassport.toISOString()}`,
581
+ received: `${expiryDatePassport?.toISOString() ?? expiryDateIDCard?.toISOString()}`,
572
582
  message: "Expiry date does not match the expected expiry date",
573
583
  };
574
584
  }
@@ -579,7 +589,7 @@ class ZKPassport {
579
589
  isCorrect = false;
580
590
  queryResultErrors.expiry_date.disclose = {
581
591
  expected: `${queryResult.expiry_date.disclose.result.toISOString()}`,
582
- received: `${expiryDatePassport.toISOString()}`,
592
+ received: `${expiryDatePassport?.toISOString() ?? expiryDateIDCard?.toISOString()}`,
583
593
  message: "Expiry date does not match the disclosed expiry date in query result",
584
594
  };
585
595
  }
@@ -595,7 +605,7 @@ class ZKPassport {
595
605
  isCorrect = false;
596
606
  queryResultErrors.nationality.eq = {
597
607
  expected: `${queryResult.nationality.eq.expected}`,
598
- received: `${nationalityPassport}`,
608
+ received: `${nationalityPassport ?? nationalityIDCard}`,
599
609
  message: "Nationality does not match the expected nationality",
600
610
  };
601
611
  }
@@ -606,7 +616,7 @@ class ZKPassport {
606
616
  isCorrect = false;
607
617
  queryResultErrors.nationality.disclose = {
608
618
  expected: `${queryResult.nationality.disclose.result}`,
609
- received: `${nationalityPassport}`,
619
+ received: `${nationalityPassport ?? nationalityIDCard}`,
610
620
  message: "Nationality does not match the disclosed nationality in query result",
611
621
  };
612
622
  }
@@ -622,7 +632,7 @@ class ZKPassport {
622
632
  isCorrect = false;
623
633
  queryResultErrors.document_number.eq = {
624
634
  expected: `${queryResult.document_number.eq.expected}`,
625
- received: `${documentNumberPassport}`,
635
+ received: `${documentNumberPassport ?? documentNumberIDCard}`,
626
636
  message: "Document number does not match the expected document number",
627
637
  };
628
638
  }
@@ -633,7 +643,7 @@ class ZKPassport {
633
643
  isCorrect = false;
634
644
  queryResultErrors.document_number.disclose = {
635
645
  expected: `${queryResult.document_number.disclose.result}`,
636
- received: `${documentNumberPassport}`,
646
+ received: `${documentNumberPassport ?? documentNumberIDCard}`,
637
647
  message: "Document number does not match the disclosed document number in query result",
638
648
  };
639
649
  }
@@ -649,7 +659,7 @@ class ZKPassport {
649
659
  isCorrect = false;
650
660
  queryResultErrors.gender.eq = {
651
661
  expected: `${queryResult.gender.eq.expected}`,
652
- received: `${genderPassport}`,
662
+ received: `${genderPassport ?? genderIDCard}`,
653
663
  message: "Gender does not match the expected gender",
654
664
  };
655
665
  }
@@ -660,7 +670,7 @@ class ZKPassport {
660
670
  isCorrect = false;
661
671
  queryResultErrors.gender.disclose = {
662
672
  expected: `${queryResult.gender.disclose.result}`,
663
- received: `${genderPassport}`,
673
+ received: `${genderPassport ?? genderIDCard}`,
664
674
  message: "Gender does not match the disclosed gender in query result",
665
675
  };
666
676
  }
@@ -676,7 +686,7 @@ class ZKPassport {
676
686
  isCorrect = false;
677
687
  queryResultErrors.issuing_country.eq = {
678
688
  expected: `${queryResult.issuing_country.eq.expected}`,
679
- received: `${issuingCountryPassport}`,
689
+ received: `${issuingCountryPassport ?? issuingCountryIDCard}`,
680
690
  message: "Issuing country does not match the expected issuing country",
681
691
  };
682
692
  }
@@ -687,7 +697,7 @@ class ZKPassport {
687
697
  isCorrect = false;
688
698
  queryResultErrors.issuing_country.disclose = {
689
699
  expected: `${queryResult.issuing_country.disclose.result}`,
690
- received: `${issuingCountryPassport}`,
700
+ received: `${issuingCountryPassport ?? issuingCountryIDCard}`,
691
701
  message: "Issuing country does not match the disclosed issuing country in query result",
692
702
  };
693
703
  }
@@ -705,7 +715,7 @@ class ZKPassport {
705
715
  isCorrect = false;
706
716
  queryResultErrors.fullname.eq = {
707
717
  expected: `${queryResult.fullname.eq.expected}`,
708
- received: `${fullnamePassport}`,
718
+ received: `${fullnamePassport ?? fullnameIDCard}`,
709
719
  message: "Fullname does not match the expected fullname",
710
720
  };
711
721
  }
@@ -718,7 +728,7 @@ class ZKPassport {
718
728
  isCorrect = false;
719
729
  queryResultErrors.fullname.disclose = {
720
730
  expected: `${queryResult.fullname.disclose.result}`,
721
- received: `${fullnamePassport}`,
731
+ received: `${fullnamePassport ?? fullnameIDCard}`,
722
732
  message: "Fullname does not match the disclosed fullname in query result",
723
733
  };
724
734
  }
@@ -741,7 +751,7 @@ class ZKPassport {
741
751
  isCorrect = false;
742
752
  queryResultErrors.firstname.eq = {
743
753
  expected: `${queryResult.firstname.eq.expected}`,
744
- received: `${firstnamePassport}`,
754
+ received: `${firstnamePassport ?? firstnameIDCard}`,
745
755
  message: "Firstname does not match the expected firstname",
746
756
  };
747
757
  }
@@ -754,7 +764,7 @@ class ZKPassport {
754
764
  isCorrect = false;
755
765
  queryResultErrors.firstname.disclose = {
756
766
  expected: `${queryResult.firstname.disclose.result}`,
757
- received: `${firstnamePassport}`,
767
+ received: `${firstnamePassport ?? firstnameIDCard}`,
758
768
  message: "Firstname does not match the disclosed firstname in query result",
759
769
  };
760
770
  }
@@ -777,7 +787,7 @@ class ZKPassport {
777
787
  isCorrect = false;
778
788
  queryResultErrors.lastname.eq = {
779
789
  expected: `${queryResult.lastname.eq.expected}`,
780
- received: `${lastnamePassport}`,
790
+ received: `${lastnamePassport ?? lastnameIDCard}`,
781
791
  message: "Lastname does not match the expected lastname",
782
792
  };
783
793
  }
@@ -790,7 +800,7 @@ class ZKPassport {
790
800
  isCorrect = false;
791
801
  queryResultErrors.lastname.disclose = {
792
802
  expected: `${queryResult.lastname.disclose.result}`,
793
- received: `${lastnamePassport}`,
803
+ received: `${lastnamePassport ?? lastnameIDCard}`,
794
804
  message: "Lastname does not match the disclosed lastname in query result",
795
805
  };
796
806
  }
@@ -894,7 +904,7 @@ class ZKPassport {
894
904
  message: "Current date in the proof is too old",
895
905
  };
896
906
  }
897
- uniqueIdentifier = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData).toString(10);
907
+ uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
898
908
  }
899
909
  else if (proof.name === "compare_birthdate") {
900
910
  commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
@@ -975,7 +985,7 @@ class ZKPassport {
975
985
  message: "Birthdate is not set in the query result",
976
986
  };
977
987
  }
978
- uniqueIdentifier = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData).toString(10);
988
+ uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
979
989
  }
980
990
  else if (proof.name === "compare_expiry") {
981
991
  commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
@@ -1058,15 +1068,15 @@ class ZKPassport {
1058
1068
  }
1059
1069
  uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1060
1070
  }
1061
- else if (proof.name === "exclusion_check_country") {
1071
+ else if (proof.name === "exclusion_check_nationality") {
1062
1072
  commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1063
1073
  if (commitmentIn !== commitmentOut) {
1064
- console.warn("Failed to check the link between the validity of the ID and the country exclusion check");
1074
+ console.warn("Failed to check the link between the validity of the ID and the nationality exclusion check");
1065
1075
  isCorrect = false;
1066
1076
  queryResultErrors.nationality.commitment = {
1067
1077
  expected: `Commitment: ${commitmentOut}`,
1068
1078
  received: `Commitment: ${commitmentIn}`,
1069
- message: "Failed to check the link between the validity of the ID and the country exclusion check",
1079
+ message: "Failed to check the link between the validity of the ID and the nationality exclusion check",
1070
1080
  };
1071
1081
  }
1072
1082
  const countryList = (0, utils_1.getCountryListFromExclusionProof)(proofData);
@@ -1074,12 +1084,12 @@ class ZKPassport {
1074
1084
  queryResult.nationality.out &&
1075
1085
  queryResult.nationality.out.result) {
1076
1086
  if (!queryResult.nationality.out.expected?.every((country) => countryList.includes(country))) {
1077
- console.warn("Country exclusion list does not match the one from the query results");
1087
+ console.warn("Nationality exclusion list does not match the one from the query results");
1078
1088
  isCorrect = false;
1079
1089
  queryResultErrors.nationality.out = {
1080
1090
  expected: queryResult.nationality.out.expected,
1081
1091
  received: countryList,
1082
- message: "Country exclusion list does not match the one from the query results",
1092
+ message: "Nationality exclusion list does not match the one from the query results",
1083
1093
  };
1084
1094
  }
1085
1095
  }
@@ -1104,15 +1114,61 @@ class ZKPassport {
1104
1114
  }
1105
1115
  uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1106
1116
  }
1107
- else if (proof.name === "inclusion_check_country") {
1117
+ else if (proof.name === "exclusion_check_issuing_country") {
1118
+ commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1119
+ if (commitmentIn !== commitmentOut) {
1120
+ console.warn("Failed to check the link between the validity of the ID and the issuing country exclusion check");
1121
+ isCorrect = false;
1122
+ queryResultErrors.nationality.commitment = {
1123
+ expected: `Commitment: ${commitmentOut}`,
1124
+ received: `Commitment: ${commitmentIn}`,
1125
+ message: "Failed to check the link between the validity of the ID and the issuing country exclusion check",
1126
+ };
1127
+ }
1128
+ const countryList = (0, utils_1.getCountryListFromExclusionProof)(proofData);
1129
+ if (queryResult.issuing_country &&
1130
+ queryResult.issuing_country.out &&
1131
+ queryResult.issuing_country.out.result) {
1132
+ if (!queryResult.issuing_country.out.expected?.every((country) => countryList.includes(country))) {
1133
+ console.warn("Issuing country exclusion list does not match the one from the query results");
1134
+ isCorrect = false;
1135
+ queryResultErrors.issuing_country.out = {
1136
+ expected: queryResult.issuing_country.out.expected,
1137
+ received: countryList,
1138
+ message: "Issuing country exclusion list does not match the one from the query results",
1139
+ };
1140
+ }
1141
+ }
1142
+ else if (!queryResult.issuing_country || !queryResult.issuing_country.out) {
1143
+ console.warn("Issuing country exclusion is not set in the query result");
1144
+ isCorrect = false;
1145
+ queryResultErrors.issuing_country.out = {
1146
+ message: "Issuing country exclusion is not set in the query result",
1147
+ };
1148
+ }
1149
+ // Check the countryList is in ascending order
1150
+ // If the prover doesn't use a sorted list then the proof cannot be trusted
1151
+ // as it is requirement in the circuit for the exclusion check to work
1152
+ for (let i = 1; i < countryList.length; i++) {
1153
+ if (countryList[i] < countryList[i - 1]) {
1154
+ console.warn("The issuing country exclusion list has not been sorted, and thus the proof cannot be trusted");
1155
+ isCorrect = false;
1156
+ queryResultErrors.issuing_country.out = {
1157
+ message: "The issuing country exclusion list has not been sorted, and thus the proof cannot be trusted",
1158
+ };
1159
+ }
1160
+ }
1161
+ uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1162
+ }
1163
+ else if (proof.name === "inclusion_check_nationality") {
1108
1164
  commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1109
1165
  if (commitmentIn !== commitmentOut) {
1110
- console.warn("Failed to check the link between the validity of the ID and the country inclusion check");
1166
+ console.warn("Failed to check the link between the validity of the ID and the nationality inclusion check");
1111
1167
  isCorrect = false;
1112
1168
  queryResultErrors.nationality.commitment = {
1113
1169
  expected: `Commitment: ${commitmentOut}`,
1114
1170
  received: `Commitment: ${commitmentIn}`,
1115
- message: "Failed to check the link between the validity of the ID and the country inclusion check",
1171
+ message: "Failed to check the link between the validity of the ID and the nationality inclusion check",
1116
1172
  };
1117
1173
  }
1118
1174
  const countryList = (0, utils_1.getCountryListFromInclusionProof)(proofData);
@@ -1120,12 +1176,12 @@ class ZKPassport {
1120
1176
  queryResult.nationality.in &&
1121
1177
  queryResult.nationality.in.result) {
1122
1178
  if (!queryResult.nationality.in.expected?.every((country) => countryList.includes(country))) {
1123
- console.warn("Country inclusion list does not match the one from the query results");
1179
+ console.warn("Nationality inclusion list does not match the one from the query results");
1124
1180
  isCorrect = false;
1125
1181
  queryResultErrors.nationality.in = {
1126
1182
  expected: queryResult.nationality.in.expected,
1127
1183
  received: countryList,
1128
- message: "Country inclusion list does not match the one from the query results",
1184
+ message: "Nationality inclusion list does not match the one from the query results",
1129
1185
  };
1130
1186
  }
1131
1187
  }
@@ -1138,40 +1194,64 @@ class ZKPassport {
1138
1194
  }
1139
1195
  uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1140
1196
  }
1197
+ else if (proof.name === "inclusion_check_issuing_country") {
1198
+ commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1199
+ if (commitmentIn !== commitmentOut) {
1200
+ console.warn("Failed to check the link between the validity of the ID and the issuing country inclusion check");
1201
+ isCorrect = false;
1202
+ queryResultErrors.nationality.commitment = {
1203
+ expected: `Commitment: ${commitmentOut}`,
1204
+ received: `Commitment: ${commitmentIn}`,
1205
+ message: "Failed to check the link between the validity of the ID and the issuing country inclusion check",
1206
+ };
1207
+ }
1208
+ const countryList = (0, utils_1.getCountryListFromInclusionProof)(proofData);
1209
+ if (queryResult.issuing_country &&
1210
+ queryResult.issuing_country.in &&
1211
+ queryResult.issuing_country.in.result) {
1212
+ if (!queryResult.issuing_country.in.expected?.every((country) => countryList.includes(country))) {
1213
+ console.warn("Issuing country inclusion list does not match the one from the query results");
1214
+ isCorrect = false;
1215
+ queryResultErrors.issuing_country.in = {
1216
+ expected: queryResult.issuing_country.in.expected,
1217
+ received: countryList,
1218
+ message: "Issuing country inclusion list does not match the one from the query results",
1219
+ };
1220
+ }
1221
+ }
1222
+ else if (!queryResult.issuing_country || !queryResult.issuing_country.in) {
1223
+ console.warn("Issuing country inclusion is not set in the query result");
1224
+ isCorrect = false;
1225
+ queryResultErrors.issuing_country.in = {
1226
+ message: "Issuing country inclusion is not set in the query result",
1227
+ };
1228
+ }
1229
+ uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1230
+ }
1141
1231
  }
1142
1232
  return { isCorrect, uniqueIdentifier, queryResultErrors };
1143
1233
  }
1144
1234
  /**
1145
1235
  * @notice Verify the proofs received from the mobile app.
1146
- * @param requestId The request ID.
1147
1236
  * @param proofs The proofs to verify.
1148
1237
  * @param queryResult The query result to verify against
1238
+ * @param validity How many days ago should have the ID been last scanned by the user?
1149
1239
  * @returns An object containing the unique identifier associated to the user
1150
1240
  * and a boolean indicating whether the proofs were successfully verified.
1151
1241
  */
1152
- async verify(requestId, proofs, queryResult) {
1153
- let proofsToVerify = proofs;
1154
- // There is a minimum of 4 subproofs to make a complete proof
1155
- if (!proofs || proofs.length < 4) {
1156
- proofsToVerify = this.topicToProofs[requestId];
1157
- }
1242
+ async verify({ proofs, queryResult, validity, }) {
1158
1243
  const { BarretenbergVerifier } = await Promise.resolve().then(() => tslib_1.__importStar(require("@aztec/bb.js")));
1159
1244
  const verifier = new BarretenbergVerifier();
1160
- /*if (!this.wasmVerifierInit) {
1161
- await this.initWasmVerifier()
1162
- }*/
1163
1245
  let verified = true;
1164
1246
  let uniqueIdentifier;
1165
1247
  let queryResultErrors;
1166
- if (queryResult) {
1167
- const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs, queryResultErrors: queryResultErrorsFromPublicInputs, } = await this.checkPublicInputs(proofsToVerify, queryResult, requestId);
1168
- uniqueIdentifier = uniqueIdentifierFromPublicInputs;
1169
- verified = isCorrect;
1170
- queryResultErrors = isCorrect ? undefined : queryResultErrorsFromPublicInputs;
1171
- }
1248
+ const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs, queryResultErrors: queryResultErrorsFromPublicInputs, } = await this.checkPublicInputs(proofs, queryResult, validity);
1249
+ uniqueIdentifier = uniqueIdentifierFromPublicInputs;
1250
+ verified = isCorrect;
1251
+ queryResultErrors = isCorrect ? undefined : queryResultErrorsFromPublicInputs;
1172
1252
  // Only proceed with the proof verification if the public inputs are correct
1173
- if (verified && queryResult) {
1174
- for (const proof of proofsToVerify) {
1253
+ if (verified) {
1254
+ for (const proof of proofs) {
1175
1255
  const proofData = (0, utils_1.getProofData)(proof.proof, true);
1176
1256
  const hostedPackagedCircuit = await (0, utils_1.getHostedPackagedCircuitByName)(proof.version, proof.name);
1177
1257
  const vkeyBytes = buffer_1.Buffer.from(hostedPackagedCircuit.vkey, "base64");
@@ -1189,7 +1269,8 @@ class ZKPassport {
1189
1269
  }
1190
1270
  }
1191
1271
  }
1192
- this.topicToProofs[requestId] = [];
1272
+ // If the proofs are not verified, we don't return the unique identifier
1273
+ uniqueIdentifier = verified ? uniqueIdentifier : undefined;
1193
1274
  return { uniqueIdentifier, verified, queryResultErrors };
1194
1275
  }
1195
1276
  /**
@@ -125,13 +125,13 @@ export type QueryBuilder = {
125
125
  * @param key The attribute to compare.
126
126
  * @param value The list of values to check inclusion against.
127
127
  */
128
- in: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder;
128
+ in: <T extends "nationality" | "issuing_country">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder;
129
129
  /**
130
130
  * Requires this attribute to be excluded from the provided list.
131
131
  * @param key The attribute to compare.
132
132
  * @param value The list of values to check exclusion against.
133
133
  */
134
- out: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder;
134
+ out: <T extends "nationality" | "issuing_country">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder;
135
135
  /**
136
136
  * Requires this attribute to be disclosed.
137
137
  * @param key The attribute to disclose.
@@ -200,13 +200,17 @@ export declare class ZKPassport {
200
200
  private checkPublicInputs;
201
201
  /**
202
202
  * @notice Verify the proofs received from the mobile app.
203
- * @param requestId The request ID.
204
203
  * @param proofs The proofs to verify.
205
204
  * @param queryResult The query result to verify against
205
+ * @param validity How many days ago should have the ID been last scanned by the user?
206
206
  * @returns An object containing the unique identifier associated to the user
207
207
  * and a boolean indicating whether the proofs were successfully verified.
208
208
  */
209
- verify(requestId: string, proofs?: Array<ProofResult>, queryResult?: QueryResult): Promise<{
209
+ verify({ proofs, queryResult, validity, }: {
210
+ proofs: Array<ProofResult>;
211
+ queryResult: QueryResult;
212
+ validity?: number;
213
+ }): Promise<{
210
214
  uniqueIdentifier: string | undefined;
211
215
  verified: boolean;
212
216
  queryResultErrors?: QueryResultErrors;