@reclaimprotocol/js-sdk 5.0.0-dev.1 → 5.0.0-dev.3

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/index.js CHANGED
@@ -22,6 +22,18 @@ var __spreadValues = (a, b) => {
22
22
  return a;
23
23
  };
24
24
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __objRest = (source, exclude) => {
26
+ var target = {};
27
+ for (var prop in source)
28
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
29
+ target[prop] = source[prop];
30
+ if (source != null && __getOwnPropSymbols)
31
+ for (var prop of __getOwnPropSymbols(source)) {
32
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
33
+ target[prop] = source[prop];
34
+ }
35
+ return target;
36
+ };
25
37
  var __commonJS = (cb, mod) => function __require() {
26
38
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
27
39
  };
@@ -72,7 +84,7 @@ var require_package = __commonJS({
72
84
  "package.json"(exports2, module2) {
73
85
  module2.exports = {
74
86
  name: "@reclaimprotocol/js-sdk",
75
- version: "5.0.0-dev.1",
87
+ version: "5.0.0-dev.3",
76
88
  description: "Designed to request proofs from the Reclaim protocol and manage the flow of claims and witness interactions.",
77
89
  main: "dist/index.js",
78
90
  types: "dist/index.d.ts",
@@ -148,6 +160,8 @@ var require_package = __commonJS({
148
160
  "@commitlint/config-conventional": "^17.7.0",
149
161
  "@release-it/conventional-changelog": "10.0.6",
150
162
  "@types/jest": "^30.0.0",
163
+ "@types/node-forge": "^1.3.14",
164
+ "@types/qrcode": "^1.5.5",
151
165
  "@types/qs": "^6.9.11",
152
166
  "@types/url-parse": "^1.4.11",
153
167
  "@types/uuid": "^9.0.7",
@@ -163,6 +177,8 @@ var require_package = __commonJS({
163
177
  canonicalize: "^2.0.0",
164
178
  ethers: "^6.9.1",
165
179
  "fetch-retry": "^6.0.0",
180
+ "node-forge": "^1.3.3",
181
+ qrcode: "^1.5.4",
166
182
  "url-parse": "^1.5.10",
167
183
  uuid: "^9.0.1"
168
184
  },
@@ -177,14 +193,16 @@ var require_package = __commonJS({
177
193
  var index_exports = {};
178
194
  __export(index_exports, {
179
195
  ReclaimProofRequest: () => ReclaimProofRequest,
196
+ TeeVerificationError: () => TeeVerificationError,
180
197
  assertValidProofsByHash: () => assertValidProofsByHash,
181
198
  assertValidateProof: () => assertValidateProof,
182
199
  assertVerifiedProof: () => assertVerifiedProof,
183
200
  clearDeviceCache: () => clearDeviceCache,
184
201
  createLinkWithTemplateData: () => createLinkWithTemplateData,
185
- fetchProviderConfig: () => fetchProviderConfig,
202
+ fetchProviderConfigs: () => fetchProviderConfigs,
186
203
  fetchProviderHashRequirementsBy: () => fetchProviderHashRequirementsBy,
187
204
  fetchStatusUrl: () => fetchStatusUrl,
205
+ generateSpecsFromRequestSpecTemplate: () => generateSpecsFromRequestSpecTemplate,
188
206
  getAttestors: () => getAttestors,
189
207
  getDeviceType: () => getDeviceType,
190
208
  getHttpProviderClaimParamsFromProof: () => getHttpProviderClaimParamsFromProof,
@@ -197,9 +215,12 @@ __export(index_exports, {
197
215
  isHttpProviderClaimParams: () => isHttpProviderClaimParams,
198
216
  isMobileDevice: () => isMobileDevice,
199
217
  recoverSignersOfSignedClaim: () => recoverSignersOfSignedClaim,
218
+ takePairsWhereValueIsArray: () => takePairsWhereValueIsArray,
219
+ takeTemplateParametersFromProofs: () => takeTemplateParametersFromProofs,
200
220
  transformForOnchain: () => transformForOnchain,
201
221
  updateSession: () => updateSession,
202
- verifyProof: () => verifyProof
222
+ verifyProof: () => verifyProof,
223
+ verifyTeeAttestation: () => verifyTeeAttestation
203
224
  });
204
225
  module.exports = __toCommonJS(index_exports);
205
226
 
@@ -212,20 +233,20 @@ var RECLAIM_EXTENSION_ACTIONS = {
212
233
  };
213
234
 
214
235
  // src/Reclaim.ts
215
- var import_ethers4 = require("ethers");
236
+ var import_ethers5 = require("ethers");
216
237
  var import_canonicalize3 = __toESM(require("canonicalize"));
217
238
 
218
239
  // src/utils/errors.ts
219
240
  function createErrorClass(name) {
220
241
  return class extends Error {
221
242
  constructor(message, innerError) {
222
- const fullMessage = innerError ? `${message || ""} caused by ${innerError.name}: ${innerError.message}` : message;
243
+ const fullMessage = innerError ? `${message || ""} caused by ${innerError && typeof innerError === "object" && "name" in innerError ? innerError.name : "Error"}: ${innerError && typeof innerError === "object" && "message" in innerError ? innerError.message : String(innerError)}` : message;
223
244
  super(fullMessage);
224
245
  this.innerError = innerError;
225
246
  this.name = name;
226
247
  if (innerError) {
227
248
  this.stack += `
228
- Caused by: ${innerError.stack}`;
249
+ Caused by: ${innerError && typeof innerError === "object" && "stack" in innerError ? innerError.stack : String(innerError)}`;
229
250
  }
230
251
  }
231
252
  };
@@ -233,6 +254,7 @@ Caused by: ${innerError.stack}`;
233
254
  var TimeoutError = createErrorClass("TimeoutError");
234
255
  var ProofNotVerifiedError = createErrorClass("ProofNotVerifiedError");
235
256
  var ProofNotValidatedError = createErrorClass("ProofNotValidatedError");
257
+ var InvalidRequestSpecError = createErrorClass("InvalidRequestSpecError");
236
258
  var UnknownProofsNotValidatedError = createErrorClass("UnknownProofsNotValidatedError");
237
259
  var SessionNotStartedError = createErrorClass("SessionNotStartedError");
238
260
  var ProviderNotFoundError = createErrorClass("ProviderNotFoundError");
@@ -258,6 +280,7 @@ var InavlidParametersError = createErrorClass("InavlidParametersError");
258
280
  var ProofSubmissionFailedError = createErrorClass("ProofSubmissionFailedError");
259
281
  var ErrorDuringVerificationError = createErrorClass("ErrorDuringVerificationError");
260
282
  var CallbackUrlRequiredError = createErrorClass("CallbackUrlRequiredError");
283
+ var TeeVerificationError = createErrorClass("TeeVerificationError");
261
284
 
262
285
  // src/utils/logger.ts
263
286
  var SimpleLogger = class {
@@ -353,15 +376,13 @@ var constants = {
353
376
  get DEFAULT_ATTESTORS_URL() {
354
377
  return `${BACKEND_BASE_URL}/api/attestors`;
355
378
  },
356
- DEFAULT_PROVIDER_URL(providerId, exactProviderVersionString) {
357
- return `${BACKEND_BASE_URL}/api/providers/${providerId}?versionNumber=${exactProviderVersionString}`;
379
+ DEFAULT_PROVIDER_CONFIGS_URL(providerId, exactProviderVersionString, allowedTags) {
380
+ return `${BACKEND_BASE_URL}/api/providers/${providerId}/configs?versionNumber=${exactProviderVersionString || ""}&allowedTags=${(allowedTags == null ? void 0 : allowedTags.join(",")) || ""}`;
358
381
  },
359
382
  // URL for sharing Reclaim templates
360
383
  RECLAIM_SHARE_URL: "https://share.reclaimprotocol.org/verifier/?template=",
361
384
  // Chrome extension URL for Reclaim Protocol
362
- CHROME_EXTENSION_URL: "https://chromewebstore.google.com/detail/reclaim-extension/oafieibbbcepkmenknelhmgaoahamdeh",
363
- // QR Code API base URL
364
- QR_CODE_API_URL: "https://api.qrserver.com/v1/create-qr-code/"
385
+ CHROME_EXTENSION_URL: "https://chromewebstore.google.com/detail/reclaim-extension/oafieibbbcepkmenknelhmgaoahamdeh"
365
386
  };
366
387
 
367
388
  // src/utils/validationUtils.ts
@@ -602,92 +623,6 @@ var http = {
602
623
  }
603
624
  };
604
625
 
605
- // src/witness.ts
606
- var import_ethers2 = require("ethers");
607
- function createSignDataForClaim(data) {
608
- const identifier = getIdentifierFromClaimInfo(data);
609
- const lines = [
610
- identifier,
611
- data.owner.toLowerCase(),
612
- data.timestampS.toString(),
613
- data.epoch.toString()
614
- ];
615
- return lines.join("\n");
616
- }
617
- function getIdentifierFromClaimInfo(info) {
618
- let canonicalContext = info.context || "";
619
- if (canonicalContext.length > 0) {
620
- try {
621
- const ctx = JSON.parse(canonicalContext);
622
- canonicalContext = canonicalStringify(ctx);
623
- } catch (e) {
624
- throw new Error("unable to parse non-empty context. Must be JSON");
625
- }
626
- }
627
- const str = `${info.provider}
628
- ${info.parameters}
629
- ${canonicalContext}`;
630
- return import_ethers2.ethers.keccak256(strToUint8Array(str)).toLowerCase();
631
- }
632
- function hashProofClaimParams(params) {
633
- const serializedParams = getProviderParamsAsCanonicalizedString(params);
634
- return import_ethers2.ethers.keccak256(
635
- strToUint8Array(serializedParams)
636
- ).toLowerCase();
637
- }
638
- function strToUint8Array(str) {
639
- return new TextEncoder().encode(str);
640
- }
641
- function getProviderParamsAsCanonicalizedString(params) {
642
- var _a, _b, _c, _d, _e, _f, _g;
643
- const filteredParams = {
644
- url: (_a = params == null ? void 0 : params.url) != null ? _a : "",
645
- // METHOD needs to be explicitly specified and absence or unknown method should cause error, but we're choosing to ignore it in this case
646
- method: (_b = params == null ? void 0 : params.method) != null ? _b : "GET",
647
- body: (_c = params == null ? void 0 : params.body) != null ? _c : "",
648
- responseMatches: (_e = (_d = params == null ? void 0 : params.responseMatches) == null ? void 0 : _d.map((it) => {
649
- var _a2, _b2;
650
- return {
651
- value: (_a2 = it.value) != null ? _a2 : "",
652
- // This needs to be explicitly specified and absence should cause error, but we're choosing to ignore it in this case
653
- type: (_b2 = it.type) != null ? _b2 : "contains",
654
- invert: it.invert || void 0,
655
- isOptional: it.isOptional || void 0
656
- };
657
- })) != null ? _e : [],
658
- responseRedactions: (_g = (_f = params == null ? void 0 : params.responseRedactions) == null ? void 0 : _f.map((it) => {
659
- var _a2, _b2, _c2;
660
- return {
661
- xPath: (_a2 = it.xPath) != null ? _a2 : "",
662
- jsonPath: (_b2 = it.jsonPath) != null ? _b2 : "",
663
- regex: (_c2 = it.regex) != null ? _c2 : "",
664
- hash: it.hash || void 0
665
- };
666
- })) != null ? _g : []
667
- };
668
- const serializedParams = canonicalStringify(filteredParams);
669
- return serializedParams;
670
- }
671
-
672
- // src/utils/providerUtils.ts
673
- function getProviderHashRequirementsFromSpec(spec) {
674
- var _a;
675
- return {
676
- hashes: ((_a = spec == null ? void 0 : spec.requests) == null ? void 0 : _a.map(hashRequestSpec)) || []
677
- };
678
- }
679
- function hashRequestSpec(request) {
680
- const hash = hashProofClaimParams(__spreadProps(__spreadValues({}, request), {
681
- // Body is strictly empty unless body sniff is explicitly enabled
682
- body: request.bodySniff.enabled ? request.bodySniff.template : ""
683
- }));
684
- return {
685
- value: hash,
686
- required: request.required,
687
- multiple: request.multiple
688
- };
689
- }
690
-
691
626
  // src/utils/sessionUtils.ts
692
627
  var logger4 = logger_default.logger;
693
628
  function initSession(providerId, appId, timestamp, signature, versionNumber) {
@@ -764,17 +699,24 @@ function fetchStatusUrl(sessionId) {
764
699
  }
765
700
  });
766
701
  }
767
- function fetchProviderConfig(providerId, exactProviderVersionString) {
702
+ function fetchProviderConfigs(providerId, exactProviderVersionString, allowedTags) {
768
703
  return __async(this, null, function* () {
769
704
  validateFunctionParams(
770
705
  [
771
- { input: providerId, paramName: "providerId", isString: true },
772
- { input: exactProviderVersionString, paramName: "exactProviderVersionString", isString: true }
706
+ { input: providerId, paramName: "providerId", isString: true }
773
707
  ],
774
- "fetchProviderConfig"
708
+ "fetchProviderConfigs"
775
709
  );
710
+ if (exactProviderVersionString != null && exactProviderVersionString != void 0) {
711
+ validateFunctionParams(
712
+ [
713
+ { input: exactProviderVersionString, paramName: "exactProviderVersionString", isString: true }
714
+ ],
715
+ "fetchProviderConfigs"
716
+ );
717
+ }
776
718
  try {
777
- const response = yield http.client(constants.DEFAULT_PROVIDER_URL(providerId, exactProviderVersionString), {
719
+ const response = yield http.client(constants.DEFAULT_PROVIDER_CONFIGS_URL(providerId, exactProviderVersionString, allowedTags), {
778
720
  method: "GET",
779
721
  headers: { "Content-Type": "application/json" }
780
722
  });
@@ -792,19 +734,116 @@ function fetchProviderConfig(providerId, exactProviderVersionString) {
792
734
  }
793
735
  });
794
736
  }
795
- function fetchProviderHashRequirementsBy(providerId, exactProviderVersion) {
796
- return __async(this, null, function* () {
797
- var _a, _b;
798
- const providerResponse = yield fetchProviderConfig(providerId, exactProviderVersion);
799
- const providerConfig = providerResponse.providers;
800
- return getProviderHashRequirementsFromSpec({
801
- requests: [...(_a = providerConfig == null ? void 0 : providerConfig.requestData) != null ? _a : [], ...(_b = providerConfig == null ? void 0 : providerConfig.allowedInjectedRequestData) != null ? _b : []]
802
- });
803
- });
804
- }
805
737
 
806
738
  // src/utils/proofUtils.ts
807
739
  var import_ethers3 = require("ethers");
740
+
741
+ // src/witness.ts
742
+ var import_ethers2 = require("ethers");
743
+ function createSignDataForClaim(data) {
744
+ const identifier = getIdentifierFromClaimInfo(data);
745
+ const lines = [
746
+ identifier,
747
+ data.owner.toLowerCase(),
748
+ data.timestampS.toString(),
749
+ data.epoch.toString()
750
+ ];
751
+ return lines.join("\n");
752
+ }
753
+ function getIdentifierFromClaimInfo(info) {
754
+ let canonicalContext = info.context || "";
755
+ if (canonicalContext.length > 0) {
756
+ try {
757
+ const ctx = JSON.parse(canonicalContext);
758
+ canonicalContext = canonicalStringify(ctx);
759
+ } catch (e) {
760
+ throw new Error("unable to parse non-empty context. Must be JSON");
761
+ }
762
+ }
763
+ const str = `${info.provider}
764
+ ${info.parameters}
765
+ ${canonicalContext}`;
766
+ return import_ethers2.ethers.keccak256(strToUint8Array(str)).toLowerCase();
767
+ }
768
+ function hashProofClaimParams(params) {
769
+ const serializedParams = getProviderParamsAsCanonicalizedString(params);
770
+ if (Array.isArray(serializedParams)) {
771
+ return serializedParams.map(
772
+ (serialized) => import_ethers2.ethers.keccak256(strToUint8Array(serialized)).toLowerCase()
773
+ );
774
+ }
775
+ return import_ethers2.ethers.keccak256(
776
+ strToUint8Array(serializedParams)
777
+ ).toLowerCase();
778
+ }
779
+ function strToUint8Array(str) {
780
+ return new TextEncoder().encode(str);
781
+ }
782
+ function getProviderParamsAsCanonicalizedString(params) {
783
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
784
+ const pairsCount = (_b = (_a = params == null ? void 0 : params.responseMatches) == null ? void 0 : _a.length) != null ? _b : 0;
785
+ const validCanonicalizedStrings = [];
786
+ const totalCombinations = 1 << pairsCount;
787
+ for (let i = 0; i < totalCombinations; i++) {
788
+ let isValidCombination = true;
789
+ let includedCount = 0;
790
+ const currentMatches = [];
791
+ const currentRedactions = [];
792
+ for (let j = 0; j < pairsCount; j++) {
793
+ const isIncluded = (i & 1 << j) !== 0;
794
+ const match = (_c = params == null ? void 0 : params.responseMatches) == null ? void 0 : _c[j];
795
+ const redaction = (_d = params == null ? void 0 : params.responseRedactions) == null ? void 0 : _d[j];
796
+ if (isIncluded) {
797
+ if (match) {
798
+ currentMatches.push({
799
+ value: (_e = match.value) != null ? _e : "",
800
+ // This needs to be explicitly specified and absence should cause error, but we're choosing to ignore it in this case
801
+ type: (_f = match.type) != null ? _f : "contains",
802
+ invert: match.invert || void 0
803
+ });
804
+ }
805
+ if (redaction) {
806
+ currentRedactions.push({
807
+ xPath: (_g = redaction.xPath) != null ? _g : "",
808
+ jsonPath: (_h = redaction.jsonPath) != null ? _h : "",
809
+ regex: (_i = redaction.regex) != null ? _i : "",
810
+ hash: redaction.hash || void 0
811
+ });
812
+ }
813
+ includedCount++;
814
+ } else {
815
+ if (match && !match.isOptional) {
816
+ isValidCombination = false;
817
+ break;
818
+ }
819
+ }
820
+ }
821
+ if (isValidCombination && includedCount > 0) {
822
+ const filteredParams = {
823
+ url: (_j = params == null ? void 0 : params.url) != null ? _j : "",
824
+ // METHOD needs to be explicitly specified and absence or unknown method should cause error, but we're choosing to ignore it in this case
825
+ method: (_k = params == null ? void 0 : params.method) != null ? _k : "GET",
826
+ body: (_l = params == null ? void 0 : params.body) != null ? _l : "",
827
+ responseMatches: currentMatches,
828
+ responseRedactions: currentRedactions
829
+ };
830
+ validCanonicalizedStrings.push(canonicalStringify(filteredParams));
831
+ }
832
+ }
833
+ if (validCanonicalizedStrings.length === 0) {
834
+ const filteredParams = {
835
+ url: (_m = params == null ? void 0 : params.url) != null ? _m : "",
836
+ method: (_n = params == null ? void 0 : params.method) != null ? _n : "GET",
837
+ body: (_o = params == null ? void 0 : params.body) != null ? _o : "",
838
+ responseMatches: [],
839
+ responseRedactions: []
840
+ };
841
+ return canonicalStringify(filteredParams);
842
+ }
843
+ return validCanonicalizedStrings.length === 1 ? validCanonicalizedStrings[0] : validCanonicalizedStrings;
844
+ }
845
+
846
+ // src/utils/proofUtils.ts
808
847
  var logger5 = logger_default.logger;
809
848
  function getShortenedUrl(url) {
810
849
  return __async(this, null, function* () {
@@ -818,7 +857,7 @@ function getShortenedUrl(url) {
818
857
  });
819
858
  const res = yield response.json();
820
859
  if (!response.ok) {
821
- logger5.info(`Failed to shorten URL: ${url}, Response: ${JSON.stringify(res)}`);
860
+ logger5.info(`Failed to shorten URL: status=${response.status}`);
822
861
  return url;
823
862
  }
824
863
  const shortenedVerificationUrl = res.result.shortUrl;
@@ -881,6 +920,7 @@ function assertVerifiedProof(proof, attestors) {
881
920
  }
882
921
 
883
922
  // src/utils/modalUtils.ts
923
+ var import_qrcode = __toESM(require("qrcode"));
884
924
  var logger6 = logger_default.logger;
885
925
  var QRCodeModal = class {
886
926
  constructor(options = {}) {
@@ -1091,17 +1131,22 @@ var QRCodeModal = class {
1091
1131
  generateQRCode(text, containerId) {
1092
1132
  return __async(this, null, function* () {
1093
1133
  try {
1094
- const qrCodeUrl = `${constants.QR_CODE_API_URL}?size=200x200&data=${encodeURIComponent(text)}`;
1134
+ const dataUrl = yield import_qrcode.default.toDataURL(text, {
1135
+ width: 200,
1136
+ margin: 1,
1137
+ color: {
1138
+ dark: "#000000",
1139
+ light: "#ffffff"
1140
+ }
1141
+ });
1095
1142
  const container = document.getElementById(containerId);
1096
1143
  const styles = this.getThemeStyles();
1097
1144
  if (container) {
1098
1145
  container.innerHTML = `
1099
- <img src="${qrCodeUrl}"
1100
- alt="QR Code for Reclaim verification"
1101
- style="width: 200px; height: 200px; border-radius: 4px;"
1102
- onerror="this.style.display='none'; this.nextElementSibling.style.display='block';">
1146
+ <img src="${dataUrl}"
1147
+ alt="QR Code for Reclaim verification"
1148
+ style="width: 200px; height: 200px; border-radius: 4px;">
1103
1149
  <div style="display: none; padding: 20px; color: ${styles.textColor}; font-size: 14px;">
1104
- QR code could not be loaded.<br>
1105
1150
  <a href="${text}" target="_blank" style="color: ${styles.linkColor}; text-decoration: underline;">
1106
1151
  Click here to open verification link
1107
1152
  </a>
@@ -1329,10 +1374,123 @@ function clearDeviceCache() {
1329
1374
  cachedMobileType = null;
1330
1375
  }
1331
1376
 
1332
- // src/utils/proofValidationUtils.ts
1377
+ // src/utils/providerUtils.ts
1333
1378
  var logger7 = logger_default.logger;
1379
+ function fetchProviderHashRequirementsBy(providerId, exactProviderVersionString, allowedTags, proofs) {
1380
+ return __async(this, null, function* () {
1381
+ var _a, _b;
1382
+ const providerResponse = yield fetchProviderConfigs(providerId, exactProviderVersionString, allowedTags);
1383
+ try {
1384
+ const providerConfigs = providerResponse.providers;
1385
+ if (!providerConfigs || !providerConfigs.length) {
1386
+ throw new ProviderConfigFetchError(`No provider configs found for providerId: ${providerId}, exactProviderVersionString: ${exactProviderVersionString}`);
1387
+ }
1388
+ const hashRequirements = [];
1389
+ for (const providerConfig of providerConfigs) {
1390
+ hashRequirements.push(getProviderHashRequirementsFromSpec({
1391
+ requests: [...(_a = providerConfig == null ? void 0 : providerConfig.requestData) != null ? _a : [], ...generateSpecsFromRequestSpecTemplate((_b = providerConfig == null ? void 0 : providerConfig.allowedInjectedRequestData) != null ? _b : [], takeTemplateParametersFromProofs(proofs))]
1392
+ }));
1393
+ }
1394
+ return hashRequirements;
1395
+ } catch (e) {
1396
+ const errorMessage = `Failed to fetch provider hash requirements for providerId: ${providerId}, exactProviderVersionString: ${exactProviderVersionString}`;
1397
+ logger7.info(errorMessage, e);
1398
+ throw new ProviderConfigFetchError(`Error fetching provider hash requirements for providerId: ${providerId}, exactProviderVersionString: ${exactProviderVersionString}`);
1399
+ }
1400
+ });
1401
+ }
1402
+ function generateSpecsFromRequestSpecTemplate(requestSpecTemplates, templateParameters) {
1403
+ var _a;
1404
+ if (!requestSpecTemplates) return [];
1405
+ const generatedRequestTemplate = [];
1406
+ for (const template of requestSpecTemplates) {
1407
+ const templateVariables = (_a = template.templateParams) != null ? _a : [];
1408
+ if (!templateVariables.length) {
1409
+ generatedRequestTemplate.push(template);
1410
+ continue;
1411
+ }
1412
+ const templateParamsPairMatch = Object.entries(templateParameters).filter(([key, value]) => templateVariables.includes(key) && value.length);
1413
+ const hasAllTemplateVariableMatch = templateParamsPairMatch.length === templateVariables.length;
1414
+ if (!hasAllTemplateVariableMatch) {
1415
+ throw new InvalidRequestSpecError(`Not all template variables are present for template`);
1416
+ }
1417
+ const templateParamsPairMatchLength = templateParamsPairMatch[0][1].length;
1418
+ const allTemplateVariablesHaveSameLength = templateParamsPairMatch.every(([key, value]) => value.length === templateParamsPairMatchLength);
1419
+ if (!allTemplateVariablesHaveSameLength) {
1420
+ throw new InvalidRequestSpecError(`Not all template variables have same length for template`);
1421
+ }
1422
+ const getRequestSpecVariableTemplate = (key) => {
1423
+ return `\${${key}}`;
1424
+ };
1425
+ for (let i = 0; i < templateParamsPairMatchLength; i++) {
1426
+ const currentTemplateParams = {};
1427
+ for (const [key, values] of templateParamsPairMatch) {
1428
+ currentTemplateParams[key] = values[i];
1429
+ }
1430
+ const spec = __spreadProps(__spreadValues({}, template), {
1431
+ responseMatches: template.responseMatches ? template.responseMatches.map((m) => __spreadValues({}, m)) : [],
1432
+ responseRedactions: template.responseRedactions ? template.responseRedactions.map((r) => __spreadValues({}, r)) : []
1433
+ });
1434
+ for (const match of spec.responseMatches) {
1435
+ for (const [key, value] of Object.entries(currentTemplateParams)) {
1436
+ match.value = match.value.split(getRequestSpecVariableTemplate(key)).join(value);
1437
+ }
1438
+ }
1439
+ for (const redaction of spec.responseRedactions) {
1440
+ for (const [key, value] of Object.entries(currentTemplateParams)) {
1441
+ redaction.jsonPath = redaction.jsonPath.split(getRequestSpecVariableTemplate(key)).join(value);
1442
+ redaction.xPath = redaction.xPath.split(getRequestSpecVariableTemplate(key)).join(value);
1443
+ redaction.regex = redaction.regex.split(getRequestSpecVariableTemplate(key)).join(value);
1444
+ }
1445
+ }
1446
+ generatedRequestTemplate.push(spec);
1447
+ }
1448
+ }
1449
+ return generatedRequestTemplate;
1450
+ }
1451
+ function takeTemplateParametersFromProofs(proofs) {
1452
+ return takePairsWhereValueIsArray(proofs == null ? void 0 : proofs.map((it) => JSON.parse(it.claimData.context).extractedParameters).reduce((acc, it) => __spreadValues(__spreadValues({}, acc), it), {}));
1453
+ }
1454
+ function takePairsWhereValueIsArray(o) {
1455
+ if (!o) return {};
1456
+ const pairs = {};
1457
+ for (const [key, value] of Object.entries(o)) {
1458
+ if (Array.isArray(value) && value.length) {
1459
+ pairs[key] = value;
1460
+ } else {
1461
+ try {
1462
+ const parsedValue = JSON.parse(value);
1463
+ if (Array.isArray(parsedValue) && parsedValue.length) {
1464
+ pairs[key] = parsedValue;
1465
+ }
1466
+ } catch (_) {
1467
+ }
1468
+ }
1469
+ }
1470
+ return pairs;
1471
+ }
1472
+ function getProviderHashRequirementsFromSpec(spec) {
1473
+ var _a;
1474
+ return {
1475
+ hashes: ((_a = spec == null ? void 0 : spec.requests) == null ? void 0 : _a.map(hashRequestSpec)) || []
1476
+ };
1477
+ }
1478
+ function hashRequestSpec(request) {
1479
+ const hash = hashProofClaimParams(__spreadProps(__spreadValues({}, request), {
1480
+ // Body is strictly empty unless body sniff is explicitly enabled
1481
+ body: request.bodySniff.enabled ? request.bodySniff.template : ""
1482
+ }));
1483
+ return {
1484
+ value: hash,
1485
+ required: request.required,
1486
+ multiple: request.multiple
1487
+ };
1488
+ }
1489
+
1490
+ // src/utils/proofValidationUtils.ts
1491
+ var logger8 = logger_default.logger;
1334
1492
  var HASH_REQUIRED_DEFAULT = true;
1335
- var HASH_MATCH_MULTIPLE_DEFAULT = false;
1493
+ var HASH_MATCH_MULTIPLE_DEFAULT = true;
1336
1494
  function assertValidProofsByHash(proofs, config) {
1337
1495
  var _a, _b;
1338
1496
  if (!config.hashes) {
@@ -1342,31 +1500,36 @@ function assertValidProofsByHash(proofs, config) {
1342
1500
  for (let i = 0; i < proofs.length; i++) {
1343
1501
  const proof = proofs[i];
1344
1502
  const claimParams = getHttpProviderClaimParamsFromProof(proof);
1345
- const computedHashOfProof = hashProofClaimParams(claimParams).toLowerCase().trim();
1346
- unvalidatedProofHashByIndex.set(i, computedHashOfProof);
1503
+ const computedHashesOfProof = hashProofClaimParams(claimParams);
1504
+ const proofHashes = Array.isArray(computedHashesOfProof) ? computedHashesOfProof.map((h) => h.toLowerCase().trim()) : [computedHashesOfProof.toLowerCase().trim()];
1505
+ unvalidatedProofHashByIndex.set(i, proofHashes);
1347
1506
  }
1348
1507
  for (const hashRequirement of config.hashes) {
1349
1508
  let found = false;
1350
- const expectedHash = hashRequirement.value.toLowerCase().trim();
1509
+ const expectedHashes = Array.isArray(hashRequirement.value) ? hashRequirement.value.map((h) => h.toLowerCase().trim()) : [hashRequirement.value.toLowerCase().trim()];
1351
1510
  const isRequired = (_a = hashRequirement.required) != null ? _a : HASH_REQUIRED_DEFAULT;
1352
1511
  const canMatchMultiple = (_b = hashRequirement.multiple) != null ? _b : HASH_MATCH_MULTIPLE_DEFAULT;
1353
- for (const [i, proofHash] of unvalidatedProofHashByIndex.entries()) {
1354
- if (proofHash === expectedHash) {
1512
+ for (const [i, proofHashes] of unvalidatedProofHashByIndex.entries()) {
1513
+ const intersection = expectedHashes.filter((eh) => proofHashes.includes(eh));
1514
+ if (intersection.length > 0) {
1355
1515
  unvalidatedProofHashByIndex.delete(i);
1356
1516
  if (!found) {
1357
1517
  found = true;
1358
1518
  } else if (!canMatchMultiple) {
1359
- throw new ProofNotValidatedError(`Proof by hash '${expectedHash}' is not allowed to appear more than once`);
1519
+ const expectedHashStr = expectedHashes.length === 1 ? expectedHashes[0] : `[${expectedHashes.join(", ")}]`;
1520
+ throw new ProofNotValidatedError(`Proof by hash '${expectedHashStr}' is not allowed to appear more than once`);
1360
1521
  }
1361
1522
  }
1362
1523
  }
1363
1524
  if (!found && isRequired) {
1364
- throw new ProofNotValidatedError(`Proof by required hash '${expectedHash}' was not found`);
1525
+ const expectedHashStr = expectedHashes.length === 1 ? expectedHashes[0] : `[${expectedHashes.join(", ")}]`;
1526
+ throw new ProofNotValidatedError(`Proof by required hash '${expectedHashStr}' was not found`);
1365
1527
  }
1366
1528
  }
1367
1529
  if (unvalidatedProofHashByIndex.size > 0) {
1368
1530
  const contactSupport = "Please contact Reclaim Protocol Support team or mail us at support@reclaimprotocol.org.";
1369
- throw new UnknownProofsNotValidatedError(`Extra ${unvalidatedProofHashByIndex.size} proof(s) by hashes ${[...unvalidatedProofHashByIndex.values()].join(", ")} was found but could not be validated and indicates a security risk. ${contactSupport}`);
1531
+ const unvalidatedHashesStrArr = [...unvalidatedProofHashByIndex.values()].map((h) => h.length === 1 ? h[0] : `[${h.join(", ")}]`);
1532
+ throw new UnknownProofsNotValidatedError(`Extra ${unvalidatedProofHashByIndex.size} proof(s) by hashes ${unvalidatedHashesStrArr.join(", ")} was found but could not be validated and indicates a security risk. ${contactSupport}`);
1370
1533
  }
1371
1534
  }
1372
1535
  var allowedHttpMethods = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
@@ -1375,7 +1538,7 @@ function isHttpProviderClaimParams(claimParams) {
1375
1538
  return false;
1376
1539
  }
1377
1540
  const params = claimParams;
1378
- return typeof params.url === "string" && typeof params.method === "string" && allowedHttpMethods.has(params.method) && typeof params.body === "string" && Array.isArray(params.responseMatches) && params.responseMatches.length > 0 && Array.isArray(params.responseRedactions);
1541
+ return typeof params.url === "string" && typeof params.method === "string" && allowedHttpMethods.has(params.method) && (params.body == null || typeof params.body === "string") && Array.isArray(params.responseMatches) && params.responseMatches.length > 0 && Array.isArray(params.responseRedactions);
1379
1542
  }
1380
1543
  function getHttpProviderClaimParamsFromProof(proof) {
1381
1544
  try {
@@ -1388,31 +1551,781 @@ function getHttpProviderClaimParamsFromProof(proof) {
1388
1551
  throw new ProofNotValidatedError("Proof has no HTTP provider params to hash");
1389
1552
  }
1390
1553
  function assertValidateProof(proofs, config) {
1391
- if ("dangerouslyDisableContentValidation" in config && config.dangerouslyDisableContentValidation) {
1392
- logger7.warn("Validation skipped because it was disabled during proof verification");
1393
- return;
1554
+ return __async(this, null, function* () {
1555
+ if ("dangerouslyDisableContentValidation" in config && config.dangerouslyDisableContentValidation) {
1556
+ logger8.warn("Validation skipped because it was disabled during proof verification");
1557
+ return;
1558
+ }
1559
+ if ("providerId" in config) {
1560
+ if (!config.providerId || typeof config.providerId !== "string") {
1561
+ throw new ProofNotValidatedError("Provider id is required for proof validation");
1562
+ }
1563
+ if (config.providerVersion && typeof config.providerVersion !== "string") {
1564
+ throw new ProofNotValidatedError("Provider version must be a string");
1565
+ }
1566
+ const hashRequirementsFromProvider = yield fetchProviderHashRequirementsBy(config.providerId, config.providerVersion, config.allowedTags, proofs);
1567
+ if (!hashRequirementsFromProvider.length) {
1568
+ throw new ProofNotValidatedError("Could not find any provider information for the given provider id and version");
1569
+ }
1570
+ if (hashRequirementsFromProvider.length != 1) {
1571
+ let lastError = null;
1572
+ for (const hashRequirement of hashRequirementsFromProvider) {
1573
+ try {
1574
+ return yield assertValidateProof(proofs, hashRequirement);
1575
+ } catch (e) {
1576
+ lastError = e;
1577
+ }
1578
+ }
1579
+ throw new ProofNotValidatedError("Could not validate proof", lastError);
1580
+ } else {
1581
+ return assertValidateProof(proofs, hashRequirementsFromProvider[0]);
1582
+ }
1583
+ }
1584
+ const effectiveHashRequirement = ("hashes" in config && Array.isArray(config == null ? void 0 : config.hashes) ? config.hashes : []).map((it) => {
1585
+ if (typeof it == "string") {
1586
+ return {
1587
+ value: it
1588
+ };
1589
+ } else {
1590
+ return it;
1591
+ }
1592
+ });
1593
+ return assertValidProofsByHash(proofs, {
1594
+ hashes: effectiveHashRequirement
1595
+ });
1596
+ });
1597
+ }
1598
+
1599
+ // src/utils/verifyTee.ts
1600
+ var import_node_forge = __toESM(require("node-forge"));
1601
+ var import_ethers4 = require("ethers");
1602
+
1603
+ // src/utils/amdCerts.ts
1604
+ var AMD_CERTS = {
1605
+ "Milan": `-----BEGIN CERTIFICATE-----
1606
+ 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
1641
+ 0YPk
1642
+ -----END CERTIFICATE-----
1643
+ -----BEGIN CERTIFICATE-----
1644
+ MIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC
1645
+ BQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS
1646
+ BgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg
1647
+ Q2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp
1648
+ Y2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy
1649
+ MTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS
1650
+ BgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j
1651
+ ZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG
1652
+ 9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg
1653
+ W41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta
1654
+ 1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2
1655
+ SzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0
1656
+ 60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05
1657
+ gmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg
1658
+ bKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs
1659
+ +gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi
1660
+ Qi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ
1661
+ eTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18
1662
+ fHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j
1663
+ WhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI
1664
+ rFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG
1665
+ KWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG
1666
+ SIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI
1667
+ AWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel
1668
+ ETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw
1669
+ STjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK
1670
+ dHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq
1671
+ zT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp
1672
+ KGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e
1673
+ pmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq
1674
+ HnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh
1675
+ 3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn
1676
+ JZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH
1677
+ CViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4
1678
+ AFZEAwoKCQ==
1679
+ -----END CERTIFICATE-----`,
1680
+ "Genoa": `-----BEGIN CERTIFICATE-----
1681
+ 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
1716
+ 2cko
1717
+ -----END CERTIFICATE-----
1718
+ -----BEGIN CERTIFICATE-----
1719
+ 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
1753
+ /wMz1R1BHg==
1754
+ -----END CERTIFICATE-----`
1755
+ };
1756
+
1757
+ // src/utils/verifyTee.ts
1758
+ var crlCache = {};
1759
+ var logger9 = logger_default.logger;
1760
+ function toUint8Array(input) {
1761
+ if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(input)) {
1762
+ return new Uint8Array(input);
1394
1763
  }
1395
- const effectiveHashRequirement = ("hashes" in config && Array.isArray(config == null ? void 0 : config.hashes) ? config.hashes : []).map((it) => {
1396
- if (typeof it == "string") {
1397
- return {
1398
- value: it
1399
- };
1764
+ if (input instanceof Uint8Array) {
1765
+ return new Uint8Array(input);
1766
+ }
1767
+ if (typeof ArrayBuffer !== "undefined" && input instanceof ArrayBuffer) {
1768
+ return new Uint8Array(input);
1769
+ }
1770
+ throw new Error("Unsupported binary data type");
1771
+ }
1772
+ function uint8ArrayToBinaryString(bytes) {
1773
+ let result = "";
1774
+ const chunkSize = 32768;
1775
+ for (let i = 0; i < bytes.length; i += chunkSize) {
1776
+ const chunk = bytes.subarray(i, i + chunkSize);
1777
+ result += String.fromCharCode(...chunk);
1778
+ }
1779
+ return result;
1780
+ }
1781
+ function binaryStringToUint8Array(binary) {
1782
+ const result = new Uint8Array(binary.length);
1783
+ for (let i = 0; i < binary.length; i++) {
1784
+ result[i] = binary.charCodeAt(i);
1785
+ }
1786
+ return result;
1787
+ }
1788
+ function base64ToUint8Array(base64) {
1789
+ if (typeof atob === "function") {
1790
+ const binary = atob(base64);
1791
+ return binaryStringToUint8Array(binary);
1792
+ }
1793
+ if (typeof Buffer !== "undefined") {
1794
+ return new Uint8Array(Buffer.from(base64, "base64"));
1795
+ }
1796
+ throw new Error("Base64 decoding is not supported in this environment");
1797
+ }
1798
+ function arrayBufferToHex(buffer) {
1799
+ const view = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
1800
+ let hex = "";
1801
+ for (let i = 0; i < view.length; i++) {
1802
+ hex += view[i].toString(16).padStart(2, "0");
1803
+ }
1804
+ return hex;
1805
+ }
1806
+ function concatUint8Arrays(parts) {
1807
+ const totalLength = parts.reduce((sum, arr) => sum + arr.length, 0);
1808
+ const result = new Uint8Array(totalLength);
1809
+ let offset = 0;
1810
+ for (const arr of parts) {
1811
+ result.set(arr, offset);
1812
+ offset += arr.length;
1813
+ }
1814
+ return result;
1815
+ }
1816
+ function reverseBytes(bytes) {
1817
+ const copy = Uint8Array.from(bytes);
1818
+ copy.reverse();
1819
+ return copy;
1820
+ }
1821
+ function normalizeSerial(s) {
1822
+ let cleaned = s.toLowerCase().replace(/[^a-f0-9]/g, "");
1823
+ while (cleaned.startsWith("0") && cleaned.length > 1) cleaned = cleaned.substring(1);
1824
+ return cleaned;
1825
+ }
1826
+ var isNode = typeof process !== "undefined" && process.versions && process.versions.node;
1827
+ var getSubtleCrypto = () => {
1828
+ var _a;
1829
+ if (typeof window !== "undefined" && ((_a = window.crypto) == null ? void 0 : _a.subtle)) return window.crypto.subtle;
1830
+ if (isNode) return require("crypto").webcrypto.subtle;
1831
+ throw new Error("No WebCrypto subtle implementation found in this environment");
1832
+ };
1833
+ function parseCert(buffer) {
1834
+ const bytes = toUint8Array(buffer);
1835
+ const asn1 = import_node_forge.default.asn1.fromDer(uint8ArrayToBinaryString(bytes));
1836
+ const certSeq = asn1.value;
1837
+ const tbsAsn1 = certSeq[0];
1838
+ const sigAlgAsn1 = certSeq[1];
1839
+ const sigValueAsn1 = certSeq[2];
1840
+ const tbsFields = tbsAsn1.value;
1841
+ let idx = 0;
1842
+ if (tbsFields[idx].tagClass === 128) idx++;
1843
+ const serialAsn1 = tbsFields[idx++];
1844
+ const serialNumber = import_node_forge.default.util.bytesToHex(serialAsn1.value);
1845
+ idx++;
1846
+ idx++;
1847
+ const validityAsn1 = tbsFields[idx++];
1848
+ idx++;
1849
+ const spkiAsn1 = tbsFields[idx];
1850
+ if (!validityAsn1 || !Array.isArray(validityAsn1.value) || validityAsn1.value.length < 2) {
1851
+ throw new Error("Certificate validity window is malformed");
1852
+ }
1853
+ const notBeforeNode = validityAsn1.value[0];
1854
+ const notAfterNode = validityAsn1.value[1];
1855
+ const notBefore = notBeforeNode ? parseAsn1Time(notBeforeNode) : void 0;
1856
+ const notAfter = notAfterNode ? parseAsn1Time(notAfterNode) : void 0;
1857
+ const sigRaw = typeof sigValueAsn1.value === "string" ? sigValueAsn1.value : "";
1858
+ const signature = binaryStringToUint8Array(sigRaw.substring(1));
1859
+ const sigAlgOid = import_node_forge.default.asn1.derToOid(sigAlgAsn1.value[0].value);
1860
+ return {
1861
+ serialNumber: normalizeSerial(serialNumber),
1862
+ tbsDer: binaryStringToUint8Array(import_node_forge.default.asn1.toDer(tbsAsn1).getBytes()),
1863
+ signature,
1864
+ sigAlgOid,
1865
+ spkiDer: binaryStringToUint8Array(import_node_forge.default.asn1.toDer(spkiAsn1).getBytes()),
1866
+ notBefore,
1867
+ notAfter
1868
+ };
1869
+ }
1870
+ function verifySignature(publicKeyPem, data, signature, sigAlgOid) {
1871
+ return __async(this, null, function* () {
1872
+ const cryptoSubtle = getSubtleCrypto();
1873
+ const forgeCert = import_node_forge.default.pki.certificateFromPem(publicKeyPem);
1874
+ const spkiBuf = binaryStringToUint8Array(import_node_forge.default.asn1.toDer(import_node_forge.default.pki.publicKeyToAsn1(forgeCert.publicKey)).getBytes());
1875
+ let importParams;
1876
+ let verifyParams;
1877
+ if (sigAlgOid === "1.2.840.113549.1.1.10") {
1878
+ importParams = { name: "RSA-PSS", hash: "SHA-384" };
1879
+ verifyParams = { name: "RSA-PSS", saltLength: 48 };
1880
+ } else if (sigAlgOid === "1.2.840.113549.1.1.11" || sigAlgOid === "1.2.840.113549.1.1.12" || sigAlgOid === "1.2.840.113549.1.1.5") {
1881
+ importParams = { name: "RSASSA-PKCS1-v1_5", hash: sigAlgOid === "1.2.840.113549.1.1.12" ? "SHA-384" : "SHA-256" };
1882
+ verifyParams = { name: "RSASSA-PKCS1-v1_5" };
1883
+ } else if (sigAlgOid === "1.2.840.10045.4.3.3") {
1884
+ importParams = { name: "ECDSA", namedCurve: "P-384" };
1885
+ verifyParams = { name: "ECDSA", hash: "SHA-384" };
1400
1886
  } else {
1401
- return it;
1887
+ importParams = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" };
1888
+ verifyParams = { name: "RSASSA-PKCS1-v1_5" };
1889
+ }
1890
+ const key = yield cryptoSubtle.importKey("spki", spkiBuf, importParams, false, ["verify"]);
1891
+ const isValid = yield cryptoSubtle.verify(verifyParams, key, signature, data);
1892
+ if (!isValid) throw new Error(`Signature verification failed (OID: ${sigAlgOid}, ImportParams: ${JSON.stringify(importParams)})`);
1893
+ });
1894
+ }
1895
+ var COSIGN_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
1896
+ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjiL30OjPuxa+GC1I7SAcBv2u2pMt
1897
+ h9WbP33IvB3eFww+C1hoW0fwdZPiq4FxBtKNiZuFpmYuFngW/nJteBu9kQ==
1898
+ -----END PUBLIC KEY-----
1899
+ `;
1900
+ function verifyTeeAttestation(proof, expectedApplicationId) {
1901
+ return __async(this, null, function* () {
1902
+ try {
1903
+ let teeAttestation = proof.teeAttestation;
1904
+ if (!teeAttestation) {
1905
+ throw new Error("Missing teeAttestation in proof");
1906
+ }
1907
+ if (typeof teeAttestation === "string") {
1908
+ teeAttestation = JSON.parse(teeAttestation);
1909
+ }
1910
+ let expectedNonceSignature;
1911
+ let nonceDataObj;
1912
+ try {
1913
+ const context = JSON.parse(proof.claimData.context);
1914
+ expectedNonceSignature = context.attestationNonce;
1915
+ nonceDataObj = context.attestationNonceData;
1916
+ } catch (e) {
1917
+ throw new Error("Failed to parse proof context to extract attestationNonce");
1918
+ }
1919
+ if (!expectedNonceSignature || !nonceDataObj) {
1920
+ throw new Error("Proof context is missing attestationNonce or attestationNonceData");
1921
+ }
1922
+ if (teeAttestation.nonce !== expectedNonceSignature) {
1923
+ throw new Error(`Nonce Mismatch! Expected signature ${expectedNonceSignature}, got ${teeAttestation.nonce}`);
1924
+ }
1925
+ const { applicationId, sessionId, timestamp } = nonceDataObj;
1926
+ if (expectedApplicationId && applicationId.toLowerCase() !== expectedApplicationId.toLowerCase()) {
1927
+ throw new Error(`Application ID Mismatch! Expected ${expectedApplicationId}, but proof context contains ${applicationId}`);
1928
+ }
1929
+ const expectedNonceData = `${applicationId}:${sessionId}:${timestamp}`;
1930
+ const nonceMsg = import_ethers4.ethers.getBytes(import_ethers4.ethers.keccak256(new TextEncoder().encode(expectedNonceData)));
1931
+ const recoveredAddress = import_ethers4.ethers.verifyMessage(nonceMsg, expectedNonceSignature);
1932
+ if (recoveredAddress.toLowerCase() !== applicationId.toLowerCase()) {
1933
+ throw new Error(`Nonce signature verification failed: recovered ${recoveredAddress}, expected ${applicationId}`);
1934
+ }
1935
+ try {
1936
+ const context = JSON.parse(proof.claimData.context);
1937
+ const paramSessionId = context.attestationNonceData.sessionId;
1938
+ if (!paramSessionId) {
1939
+ throw new Error(`Proof parameters are missing proxySessionId or sessionId`);
1940
+ }
1941
+ if (paramSessionId.toString() !== sessionId.toString()) {
1942
+ throw new Error(`Session ID Mismatch! Expected ${sessionId}, but proof parameters contain ${paramSessionId}`);
1943
+ }
1944
+ const claimTimestampMs = proof.claimData.timestampS * 1e3;
1945
+ const nonceTimestampMs = parseInt(timestamp, 10);
1946
+ const diffMs = Math.abs(claimTimestampMs - nonceTimestampMs);
1947
+ const TEN_MINUTES_MS = 10 * 60 * 1e3;
1948
+ if (diffMs > TEN_MINUTES_MS) {
1949
+ throw new Error(`Timestamp Skew Too Large! claimData.timestampS and attestationNonce timestamp differ by ${Math.round(diffMs / 1e3)}s (limit: 600s)`);
1950
+ }
1951
+ } catch (e) {
1952
+ if (e instanceof Error && (e.message.includes("Session ID Mismatch!") || e.message.includes("Timestamp Skew"))) {
1953
+ throw e;
1954
+ }
1955
+ throw new Error(`Failed to cross-verify session ID: ${e.message}`);
1956
+ }
1957
+ const reportBuffer = base64ToUint8Array(teeAttestation.snp_report);
1958
+ const report = parseAttestationReport(reportBuffer);
1959
+ if (report.isDebugEnabled) {
1960
+ throw new Error("POLICY CHECK FAILED: Debug mode is ALLOWED. Environment is compromised.");
1961
+ }
1962
+ const certBuffer = base64ToUint8Array(teeAttestation.vlek_cert);
1963
+ yield verifyAMDChain(certBuffer);
1964
+ verifyTCB(certBuffer, report);
1965
+ yield verifyHardwareSignature(reportBuffer, certBuffer);
1966
+ yield verifyReportData(teeAttestation, proof.claimData.context, report);
1967
+ return true;
1968
+ } catch (error) {
1969
+ logger9.error("TEE attestation verification failed:", error);
1970
+ return false;
1971
+ }
1972
+ });
1973
+ }
1974
+ function parseAttestationReport(buffer) {
1975
+ if (buffer.length < 1e3) {
1976
+ throw new Error(`Report buffer is too small: ${buffer.length} bytes`);
1977
+ }
1978
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
1979
+ const policy = view.getBigUint64(8, true);
1980
+ const isDebugEnabled = (policy & BigInt(1) << BigInt(19)) !== BigInt(0);
1981
+ const reported_tcb = {
1982
+ bootloader: buffer[56],
1983
+ tee: buffer[57],
1984
+ snp: buffer[62],
1985
+ microcode: buffer[63]
1986
+ };
1987
+ const reportData = arrayBufferToHex(buffer.subarray(80, 144));
1988
+ return { policy, isDebugEnabled, reported_tcb, reportData };
1989
+ }
1990
+ function getExtValue(certAsn1, oidString) {
1991
+ const tbsCert = certAsn1.value[0];
1992
+ if (!tbsCert || !tbsCert.value) return null;
1993
+ const extBlockWrapper = tbsCert.value.find((node) => node.tagClass === import_node_forge.default.asn1.Class.CONTEXT_SPECIFIC && node.type === 3);
1994
+ if (!extBlockWrapper || !extBlockWrapper.value || !extBlockWrapper.value.length) return null;
1995
+ const extSequence = extBlockWrapper.value[0];
1996
+ for (const ext of extSequence.value) {
1997
+ const extIdAsn1 = ext.value[0];
1998
+ const extIdStr = import_node_forge.default.asn1.derToOid(extIdAsn1.value);
1999
+ if (extIdStr === oidString) {
2000
+ const extValueAsn1 = ext.value[ext.value.length - 1];
2001
+ const rawOctetStringBytes = extValueAsn1.value;
2002
+ try {
2003
+ const innerAsn1 = import_node_forge.default.asn1.fromDer(import_node_forge.default.util.createBuffer(rawOctetStringBytes));
2004
+ if (innerAsn1.type === 2) {
2005
+ const bytes = innerAsn1.value;
2006
+ if (typeof bytes === "string" && bytes.length > 0) {
2007
+ return bytes.charCodeAt(bytes.length - 1);
2008
+ } else {
2009
+ throw new Error(`Extension ${oidString} INTEGER value is empty or invalid`);
2010
+ }
2011
+ } else {
2012
+ throw new Error(`Extension ${oidString} does not contain an INTEGER, found type ${innerAsn1.type}`);
2013
+ }
2014
+ } catch (e) {
2015
+ throw new Error(`Failed to strictly parse AMD TCB extension ${oidString}: ${e.message}`);
2016
+ }
2017
+ }
2018
+ }
2019
+ return null;
2020
+ }
2021
+ function verifyTCB(vlekCertBuffer, report) {
2022
+ const certAsn1 = import_node_forge.default.asn1.fromDer(import_node_forge.default.util.createBuffer(uint8ArrayToBinaryString(vlekCertBuffer)));
2023
+ const OID_BOOTLOADER = "1.3.6.1.4.1.3704.1.3.1";
2024
+ const OID_TEE = "1.3.6.1.4.1.3704.1.3.2";
2025
+ const OID_SNP = "1.3.6.1.4.1.3704.1.3.3";
2026
+ const OID_MICROCODE = "1.3.6.1.4.1.3704.1.3.8";
2027
+ const certTcb = {
2028
+ bootloader: getExtValue(certAsn1, OID_BOOTLOADER),
2029
+ tee: getExtValue(certAsn1, OID_TEE),
2030
+ snp: getExtValue(certAsn1, OID_SNP),
2031
+ microcode: getExtValue(certAsn1, OID_MICROCODE)
2032
+ };
2033
+ if (certTcb.bootloader !== null && report.reported_tcb.bootloader < certTcb.bootloader) {
2034
+ throw new Error(`TCB Downgrade! Bootloader reported ${report.reported_tcb.bootloader}, but certificate requires ${certTcb.bootloader}`);
2035
+ }
2036
+ if (certTcb.tee !== null && report.reported_tcb.tee < certTcb.tee) {
2037
+ throw new Error(`TCB Downgrade! TEE reported ${report.reported_tcb.tee}, but certificate requires ${certTcb.tee}`);
2038
+ }
2039
+ if (certTcb.snp !== null && report.reported_tcb.snp < certTcb.snp) {
2040
+ throw new Error(`TCB Downgrade! SNP reported ${report.reported_tcb.snp}, but certificate requires ${certTcb.snp}`);
2041
+ }
2042
+ if (certTcb.microcode !== null && report.reported_tcb.microcode < certTcb.microcode) {
2043
+ throw new Error(`TCB Downgrade! Microcode reported ${report.reported_tcb.microcode}, but certificate requires ${certTcb.microcode}`);
2044
+ }
2045
+ }
2046
+ function parseAsn1Time(node) {
2047
+ const s = node.value;
2048
+ if (node.type === import_node_forge.default.asn1.Type.UTCTIME) {
2049
+ const yr = parseInt(s.substring(0, 2), 10);
2050
+ return new Date(Date.UTC(
2051
+ yr >= 50 ? 1900 + yr : 2e3 + yr,
2052
+ parseInt(s.substring(2, 4), 10) - 1,
2053
+ parseInt(s.substring(4, 6), 10),
2054
+ parseInt(s.substring(6, 8), 10),
2055
+ parseInt(s.substring(8, 10), 10),
2056
+ parseInt(s.substring(10, 12), 10)
2057
+ ));
2058
+ } else {
2059
+ return new Date(Date.UTC(
2060
+ parseInt(s.substring(0, 4), 10),
2061
+ parseInt(s.substring(4, 6), 10) - 1,
2062
+ parseInt(s.substring(6, 8), 10),
2063
+ parseInt(s.substring(8, 10), 10),
2064
+ parseInt(s.substring(10, 12), 10),
2065
+ parseInt(s.substring(12, 14), 10)
2066
+ ));
2067
+ }
2068
+ }
2069
+ function verifyCRL(crlBuf, arkPem, vlekSerial) {
2070
+ return __async(this, null, function* () {
2071
+ const crlAsn1 = import_node_forge.default.asn1.fromDer(import_node_forge.default.util.createBuffer(uint8ArrayToBinaryString(crlBuf)));
2072
+ if (!Array.isArray(crlAsn1.value) || crlAsn1.value.length < 3) {
2073
+ throw new Error("CRL ASN.1 structure is invalid: expected SEQUENCE with TBSCertList, AlgorithmIdentifier, BIT STRING");
2074
+ }
2075
+ const tbsAsn1 = crlAsn1.value[0];
2076
+ const sigBitsAsn1 = crlAsn1.value[2];
2077
+ if (!Array.isArray(tbsAsn1.value)) {
2078
+ throw new Error("CRL TBSCertList is not a valid SEQUENCE");
2079
+ }
2080
+ const tbsFields = tbsAsn1.value;
2081
+ let fi = 0;
2082
+ if (fi < tbsFields.length && tbsFields[fi].tagClass === import_node_forge.default.asn1.Class.UNIVERSAL && tbsFields[fi].type === import_node_forge.default.asn1.Type.INTEGER) {
2083
+ fi++;
2084
+ }
2085
+ if (fi < tbsFields.length) fi++;
2086
+ if (fi >= tbsFields.length) throw new Error("CRL TBSCertList missing issuer");
2087
+ const issuerAsn1 = tbsFields[fi++];
2088
+ if (fi >= tbsFields.length) throw new Error("CRL TBSCertList missing thisUpdate");
2089
+ const thisUpdateAsn1 = tbsFields[fi++];
2090
+ let nextUpdateAsn1 = null;
2091
+ if (fi < tbsFields.length && tbsFields[fi].tagClass === import_node_forge.default.asn1.Class.UNIVERSAL && (tbsFields[fi].type === import_node_forge.default.asn1.Type.UTCTIME || tbsFields[fi].type === import_node_forge.default.asn1.Type.GENERALIZEDTIME)) {
2092
+ nextUpdateAsn1 = tbsFields[fi++];
2093
+ }
2094
+ let revokedSeq = null;
2095
+ if (fi < tbsFields.length && tbsFields[fi].tagClass === import_node_forge.default.asn1.Class.UNIVERSAL && tbsFields[fi].type === import_node_forge.default.asn1.Type.SEQUENCE) {
2096
+ revokedSeq = tbsFields[fi];
2097
+ }
2098
+ const now = /* @__PURE__ */ new Date();
2099
+ const thisUpdate = parseAsn1Time(thisUpdateAsn1);
2100
+ if (thisUpdate > now) {
2101
+ throw new Error(`CRL is not yet valid: thisUpdate is ${thisUpdate.toISOString()}`);
2102
+ }
2103
+ if (nextUpdateAsn1) {
2104
+ const nextUpdate = parseAsn1Time(nextUpdateAsn1);
2105
+ if (nextUpdate < now) {
2106
+ throw new Error(`CRL has expired: nextUpdate was ${nextUpdate.toISOString()}`);
2107
+ }
2108
+ }
2109
+ const crlIssuerDer = import_node_forge.default.asn1.toDer(issuerAsn1).getBytes();
2110
+ const arkForgeCert = import_node_forge.default.pki.certificateFromPem(arkPem);
2111
+ const arkCertAsn1 = import_node_forge.default.pki.certificateToAsn1(arkForgeCert);
2112
+ const arkSubjectAsn1 = arkCertAsn1.value[0].value[5];
2113
+ const arkSubjectDer = import_node_forge.default.asn1.toDer(arkSubjectAsn1).getBytes();
2114
+ if (crlIssuerDer !== arkSubjectDer) {
2115
+ throw new Error("CRL issuer does not match AMD ARK certificate subject \u2014 chain mismatch");
2116
+ }
2117
+ const tbsDerBuf = binaryStringToUint8Array(import_node_forge.default.asn1.toDer(tbsAsn1).getBytes());
2118
+ const sigRaw = typeof sigBitsAsn1.value === "string" ? sigBitsAsn1.value : "";
2119
+ const sigBuf = binaryStringToUint8Array(sigRaw.substring(1));
2120
+ const cryptoSubtle = getSubtleCrypto();
2121
+ const spkiBuf = binaryStringToUint8Array(
2122
+ import_node_forge.default.asn1.toDer(import_node_forge.default.pki.publicKeyToAsn1(arkForgeCert.publicKey)).getBytes()
2123
+ );
2124
+ const arkCryptoKey = yield cryptoSubtle.importKey(
2125
+ "spki",
2126
+ spkiBuf,
2127
+ { name: "RSA-PSS", hash: "SHA-384" },
2128
+ false,
2129
+ ["verify"]
2130
+ );
2131
+ const isValid = yield cryptoSubtle.verify(
2132
+ { name: "RSA-PSS", saltLength: 48 },
2133
+ // SHA-384 salt length is 48
2134
+ arkCryptoKey,
2135
+ sigBuf,
2136
+ tbsDerBuf
2137
+ );
2138
+ if (!isValid) {
2139
+ throw new Error("CRL signature is INVALID \u2014 the CRL may be tampered or forged");
2140
+ }
2141
+ const targetSerial = normalizeSerial(vlekSerial);
2142
+ if (revokedSeq && Array.isArray(revokedSeq.value)) {
2143
+ for (const entry of revokedSeq.value) {
2144
+ if (!Array.isArray(entry.value) || entry.value.length < 2) continue;
2145
+ const serialAsn1 = entry.value[0];
2146
+ if (serialAsn1.type !== import_node_forge.default.asn1.Type.INTEGER || typeof serialAsn1.value !== "string") continue;
2147
+ const serialHex = import_node_forge.default.util.bytesToHex(serialAsn1.value);
2148
+ if (normalizeSerial(serialHex) === targetSerial) {
2149
+ throw new Error("\u{1F6A8} VLEK Certificate is REVOKED per AMD CRL! This hardware may be compromised.");
2150
+ }
2151
+ }
2152
+ }
2153
+ });
2154
+ }
2155
+ function assertCertValidity(label, cert) {
2156
+ const now = Date.now();
2157
+ if (cert.notBefore && now < cert.notBefore.getTime()) {
2158
+ throw new Error(`${label} certificate is not yet valid (notBefore: ${cert.notBefore.toISOString()})`);
2159
+ }
2160
+ if (cert.notAfter && now > cert.notAfter.getTime()) {
2161
+ throw new Error(`${label} certificate expired on ${cert.notAfter.toISOString()}`);
2162
+ }
2163
+ }
2164
+ function verifyAMDChain(vlekCertBuffer) {
2165
+ return __async(this, null, function* () {
2166
+ const processors = ["Milan", "Genoa"];
2167
+ let chainVerified = false;
2168
+ const vlek = parseCert(vlekCertBuffer);
2169
+ assertCertValidity("VLEK", vlek);
2170
+ for (const processor of processors) {
2171
+ let matchedChain = false;
2172
+ try {
2173
+ const chainPem = AMD_CERTS[processor];
2174
+ if (!chainPem) continue;
2175
+ const certs = chainPem.split("-----END CERTIFICATE-----").map((c) => c.trim()).filter((c) => c.length > 0).map((c) => c + "\n-----END CERTIFICATE-----\n");
2176
+ const askCert = import_node_forge.default.pki.certificateFromPem(certs[0]);
2177
+ const arkCert = import_node_forge.default.pki.certificateFromPem(certs[1]);
2178
+ const askDer = import_node_forge.default.asn1.toDer(import_node_forge.default.pki.certificateToAsn1(askCert)).getBytes();
2179
+ const arkDer = import_node_forge.default.asn1.toDer(import_node_forge.default.pki.certificateToAsn1(arkCert)).getBytes();
2180
+ const ask = parseCert(binaryStringToUint8Array(askDer));
2181
+ const ark = parseCert(binaryStringToUint8Array(arkDer));
2182
+ assertCertValidity("ASK", ask);
2183
+ assertCertValidity("ARK", ark);
2184
+ try {
2185
+ yield verifySignature(certs[1], ark.tbsDer, ark.signature, ark.sigAlgOid);
2186
+ } catch (e) {
2187
+ throw new Error(`AMD ARK self-signature verification failed: ${e.message}`);
2188
+ }
2189
+ try {
2190
+ yield verifySignature(certs[1], ask.tbsDer, ask.signature, ask.sigAlgOid);
2191
+ } catch (e) {
2192
+ throw new Error(`AMD ASK-by-ARK signature verification failed: ${e.message}`);
2193
+ }
2194
+ try {
2195
+ yield verifySignature(certs[0], vlek.tbsDer, vlek.signature, vlek.sigAlgOid);
2196
+ } catch (e) {
2197
+ throw new Error(`VLEK-by-ASK signature verification failed: ${e.message}`);
2198
+ }
2199
+ matchedChain = true;
2200
+ let crlBuf;
2201
+ const now = Date.now();
2202
+ if (crlCache[processor] && now - crlCache[processor].fetchedAt < 36e5) {
2203
+ crlBuf = crlCache[processor].buffer;
2204
+ } else {
2205
+ const crlUrl = `https://kdsintf.amd.com/vlek/v1/${processor}/crl`;
2206
+ const controller = new AbortController();
2207
+ const timeoutId = setTimeout(() => controller.abort(), 5e3);
2208
+ const crlResp = yield fetch(crlUrl, { signal: controller.signal });
2209
+ clearTimeout(timeoutId);
2210
+ if (!crlResp.ok) continue;
2211
+ crlBuf = new Uint8Array(yield crlResp.arrayBuffer());
2212
+ crlCache[processor] = { buffer: crlBuf, fetchedAt: now };
2213
+ }
2214
+ if (vlek.serialNumber && crlBuf) {
2215
+ yield verifyCRL(crlBuf, certs[1], vlek.serialNumber);
2216
+ }
2217
+ chainVerified = true;
2218
+ break;
2219
+ } catch (e) {
2220
+ if (matchedChain) {
2221
+ throw e;
2222
+ }
2223
+ continue;
2224
+ }
2225
+ }
2226
+ if (!chainVerified) {
2227
+ throw new Error("VLEK Certificate failed verification against all known AMD Root of Trust chains!");
2228
+ }
2229
+ });
2230
+ }
2231
+ function verifyHardwareSignature(reportBytes, certBytes) {
2232
+ return __async(this, null, function* () {
2233
+ const vlek = parseCert(certBytes);
2234
+ const sigOffset = 672;
2235
+ const rLE = reportBytes.subarray(sigOffset, sigOffset + 72);
2236
+ const sLE = reportBytes.subarray(sigOffset + 72, sigOffset + 144);
2237
+ const rBE = reverseBytes(rLE);
2238
+ const sBE = reverseBytes(sLE);
2239
+ const signedData = reportBytes.subarray(0, 672);
2240
+ const cryptoSubtle = getSubtleCrypto();
2241
+ const importedKey = yield cryptoSubtle.importKey(
2242
+ "spki",
2243
+ vlek.spkiDer,
2244
+ { name: "ECDSA", namedCurve: "P-384" },
2245
+ false,
2246
+ ["verify"]
2247
+ );
2248
+ const rPadding = rBE.subarray(0, rBE.length - 48);
2249
+ const sPadding = sBE.subarray(0, sBE.length - 48);
2250
+ if (!rPadding.every((b) => b === 0) || !sPadding.every((b) => b === 0)) {
2251
+ throw new Error("Hardware ECDSA signature is malformed: non-zero padding bytes detected in the structural signature coordinates.");
2252
+ }
2253
+ const r48 = rBE.subarray(rBE.length - 48);
2254
+ const s48 = sBE.subarray(sBE.length - 48);
2255
+ const rawSignature = concatUint8Arrays([r48, s48]);
2256
+ const isValid = yield cryptoSubtle.verify(
2257
+ { name: "ECDSA", hash: { name: "SHA-384" } },
2258
+ importedKey,
2259
+ rawSignature,
2260
+ signedData
2261
+ );
2262
+ if (!isValid) {
2263
+ throw new Error("Hardware ECDSA signature is completely invalid!");
1402
2264
  }
1403
2265
  });
1404
- return assertValidProofsByHash(proofs, {
1405
- hashes: effectiveHashRequirement
2266
+ }
2267
+ function verifyReportData(teeAttestation, proofContext, report) {
2268
+ return __async(this, null, function* () {
2269
+ if (!teeAttestation.workload_digest || !teeAttestation.verifier_digest) {
2270
+ throw new Error("POLICY CHECK FAILED: Missing workload_digest or verifier_digest in TEE attestation.");
2271
+ }
2272
+ const { attestationNonce: nonce } = JSON.parse(proofContext);
2273
+ const cryptoSubtle = getSubtleCrypto();
2274
+ const extractDigestBytes = (imageRef) => {
2275
+ const marker = "@sha256:";
2276
+ const idx = imageRef.lastIndexOf(marker);
2277
+ if (idx < 0) throw new Error(`Image ref missing @sha256: digest: ${imageRef}`);
2278
+ const hexDigest = imageRef.substring(idx + marker.length);
2279
+ if (hexDigest.length !== 64) throw new Error(`SHA256 digest must be 64 hex chars, got ${hexDigest.length} in: ${imageRef}`);
2280
+ const bytes = new Uint8Array(32);
2281
+ for (let i = 0; i < 32; i++) bytes[i] = parseInt(hexDigest.substring(i * 2, i * 2 + 2), 16);
2282
+ return bytes;
2283
+ };
2284
+ const importedCosignKey = yield cryptoSubtle.importKey(
2285
+ "spki",
2286
+ base64ToUint8Array(
2287
+ COSIGN_PUBLIC_KEY.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").replace(/\s+/g, "")
2288
+ ),
2289
+ { name: "ECDSA", namedCurve: "P-256" },
2290
+ true,
2291
+ ["verify"]
2292
+ );
2293
+ const pubKeySpkiDer = yield cryptoSubtle.exportKey("spki", importedCosignKey);
2294
+ const pubKeyHashBuffer = yield cryptoSubtle.digest("SHA-256", pubKeySpkiDer);
2295
+ const pubKeyHashBytes = new Uint8Array(pubKeyHashBuffer);
2296
+ const nonceHex = (teeAttestation.nonce || nonce).replace(/^0x/i, "");
2297
+ const nonceBytes = new Uint8Array(nonceHex.length / 2);
2298
+ for (let i = 0; i < nonceBytes.length; i++) nonceBytes[i] = parseInt(nonceHex.substring(i * 2, i * 2 + 2), 16);
2299
+ const workloadBytes = extractDigestBytes(teeAttestation.workload_digest);
2300
+ const verifierBytes = extractDigestBytes(teeAttestation.verifier_digest);
2301
+ const domainSep = new TextEncoder().encode("POPCORN_TEE_REPORT_DATA_V1");
2302
+ const version = new Uint8Array([1]);
2303
+ const payload = new Uint8Array(
2304
+ domainSep.length + version.length + workloadBytes.length + verifierBytes.length + pubKeyHashBytes.length + nonceBytes.length
2305
+ );
2306
+ let offset = 0;
2307
+ for (const chunk of [domainSep, version, workloadBytes, verifierBytes, pubKeyHashBytes, nonceBytes]) {
2308
+ payload.set(chunk, offset);
2309
+ offset += chunk.length;
2310
+ }
2311
+ const hashBuffer = yield cryptoSubtle.digest("SHA-256", payload);
2312
+ const hashHex = arrayBufferToHex(hashBuffer);
2313
+ const expected64ByteHex = hashHex + hashHex;
2314
+ if (report.reportData !== expected64ByteHex) {
2315
+ throw new Error(`REPORT_DATA Mismatch! Hardware report is not bound to these image digests or nonce.
2316
+ Expected: ${expected64ByteHex}
2317
+ Got: ${report.reportData}`);
2318
+ }
1406
2319
  });
1407
2320
  }
1408
2321
 
1409
2322
  // src/Reclaim.ts
1410
- var logger8 = logger_default.logger;
2323
+ var logger10 = logger_default.logger;
1411
2324
  var sdkVersion = require_package().version;
1412
2325
  function verifyProof(proofOrProofs, config) {
1413
2326
  return __async(this, null, function* () {
2327
+ const proofs = Array.isArray(proofOrProofs) ? proofOrProofs : [proofOrProofs];
1414
2328
  try {
1415
- const proofs = Array.isArray(proofOrProofs) ? proofOrProofs : [proofOrProofs];
1416
2329
  if (proofs.length === 0) {
1417
2330
  throw new ProofNotValidatedError("No proofs provided");
1418
2331
  }
@@ -1423,14 +2336,64 @@ function verifyProof(proofOrProofs, config) {
1423
2336
  for (const proof of proofs) {
1424
2337
  yield assertVerifiedProof(proof, attestors);
1425
2338
  }
1426
- assertValidateProof(proofs, config);
1427
- return true;
2339
+ yield assertValidateProof(proofs, config);
2340
+ const result = {
2341
+ isVerified: true,
2342
+ data: proofs.map(extractProofData)
2343
+ };
2344
+ if (config.verifyTEE) {
2345
+ const hasTeeData = proofs.every((proof) => proof.teeAttestation || JSON.parse(proof.claimData.context).attestationNonce);
2346
+ if (!hasTeeData) {
2347
+ const teeError = new TeeVerificationError("TEE verification requested but one or more proofs are missing TEE attestation data");
2348
+ logger10.error(teeError.message);
2349
+ result.isTeeVerified = false;
2350
+ result.isVerified = false;
2351
+ result.error = teeError;
2352
+ return result;
2353
+ }
2354
+ try {
2355
+ const teeResults = yield Promise.all(proofs.map((proof) => verifyTeeAttestation(proof)));
2356
+ result.isTeeVerified = teeResults.every((r) => r === true);
2357
+ if (!result.isTeeVerified) {
2358
+ const teeError = new TeeVerificationError("TEE attestation verification failed for one or more proofs");
2359
+ logger10.error(teeError.message);
2360
+ result.isVerified = false;
2361
+ result.error = teeError;
2362
+ }
2363
+ } catch (error) {
2364
+ const teeError = new TeeVerificationError("Error verifying TEE attestation", error);
2365
+ logger10.error(teeError.message);
2366
+ result.isTeeVerified = false;
2367
+ result.isVerified = false;
2368
+ result.error = teeError;
2369
+ }
2370
+ }
2371
+ return result;
1428
2372
  } catch (error) {
1429
- logger8.error("Error in validating proof:", error);
1430
- return false;
2373
+ logger10.error("Error in validating proof:", error);
2374
+ return {
2375
+ isVerified: false,
2376
+ data: [],
2377
+ error: error instanceof Error ? error : new Error(String(error))
2378
+ };
1431
2379
  }
1432
2380
  });
1433
2381
  }
2382
+ function extractProofData(proof) {
2383
+ try {
2384
+ const context = JSON.parse(proof.claimData.context);
2385
+ const _a = context, { extractedParameters } = _a, rest = __objRest(_a, ["extractedParameters"]);
2386
+ return {
2387
+ context: rest,
2388
+ extractedParameters: extractedParameters != null ? extractedParameters : {}
2389
+ };
2390
+ } catch (e) {
2391
+ return {
2392
+ context: {},
2393
+ extractedParameters: {}
2394
+ };
2395
+ }
2396
+ }
1434
2397
  function transformForOnchain(proof) {
1435
2398
  const claimInfoBuilder = /* @__PURE__ */ new Map([
1436
2399
  ["context", proof.claimData.context],
@@ -1479,6 +2442,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1479
2442
  this.intervals = /* @__PURE__ */ new Map();
1480
2443
  this.jsonProofResponse = false;
1481
2444
  this.extensionID = "reclaim-extension";
2445
+ this.appSharePageUrl = "https://share.reclaimprotocol.org/verify";
1482
2446
  this.FAILURE_TIMEOUT = 30 * 1e3;
1483
2447
  /**
1484
2448
  * Validates signature and returns template data
@@ -1546,34 +2510,42 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1546
2510
  logger_default.setLogLevel("silent");
1547
2511
  }
1548
2512
  if (options.useAppClip === void 0) {
1549
- options.useAppClip = true;
2513
+ options.useAppClip = false;
2514
+ }
2515
+ const customUrl = (_b = options.portalUrl) != null ? _b : options.customSharePageUrl;
2516
+ this.customSharePageUrl = customUrl != null ? customUrl : "https://portal.reclaimprotocol.org";
2517
+ if (customUrl) {
2518
+ this.appSharePageUrl = customUrl;
1550
2519
  }
2520
+ options.customSharePageUrl = this.customSharePageUrl;
1551
2521
  if (options == null ? void 0 : options.envUrl) {
1552
2522
  setBackendBaseUrl(options.envUrl);
1553
- } else if ((_b = options == null ? void 0 : options.customSharePageUrl) == null ? void 0 : _b.includes("eu.portal.reclaimprotocol.org")) {
1554
- setBackendBaseUrl("https://eu.api.reclaimprotocol.org");
2523
+ } else if (this.customSharePageUrl) {
2524
+ try {
2525
+ if (new URL(this.customSharePageUrl).hostname === "eu.portal.reclaimprotocol.org") {
2526
+ setBackendBaseUrl("https://eu.api.reclaimprotocol.org");
2527
+ }
2528
+ } catch (e) {
2529
+ }
1555
2530
  }
1556
2531
  if (options.extensionID) {
1557
2532
  this.extensionID = options.extensionID;
1558
2533
  }
1559
- if (options == null ? void 0 : options.customSharePageUrl) {
1560
- this.customSharePageUrl = options.customSharePageUrl;
1561
- }
1562
2534
  if (options == null ? void 0 : options.customAppClipUrl) {
1563
2535
  this.customAppClipUrl = options.customAppClipUrl;
1564
2536
  }
1565
2537
  this.options = options;
1566
2538
  this.sdkVersion = "js-" + sdkVersion;
1567
- logger8.info(`Initializing client with applicationId: ${this.applicationId}`);
2539
+ logger10.info(`Initializing client with applicationId: ${this.applicationId}`);
1568
2540
  }
1569
2541
  /**
1570
- * Initializes a new Reclaim proof request instance with automatic signature generation and session creation
2542
+ * Initializes a new Reclaim proof request instance with automatic signature generation and session creation.
1571
2543
  *
1572
2544
  * @param applicationId - Your Reclaim application ID
1573
2545
  * @param appSecret - Your application secret key for signing requests
1574
2546
  * @param providerId - The ID of the provider to use for proof generation
1575
2547
  * @param options - Optional configuration options for the proof request
1576
- * @returns Promise<ReclaimProofRequest> - A fully initialized proof request instance
2548
+ * @returns A fully initialized proof request instance
1577
2549
  * @throws {InitError} When initialization fails due to invalid parameters or session creation errors
1578
2550
  *
1579
2551
  * @example
@@ -1582,7 +2554,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1582
2554
  * 'your-app-id',
1583
2555
  * 'your-app-secret',
1584
2556
  * 'provider-id',
1585
- * { log: true, acceptAiProviders: true }
2557
+ * { portalUrl: 'https://portal.reclaimprotocol.org', log: true }
1586
2558
  * );
1587
2559
  * ```
1588
2560
  */
@@ -1635,6 +2607,11 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1635
2607
  { paramName: "envUrl", input: options.envUrl, isString: true }
1636
2608
  ], "the constructor");
1637
2609
  }
2610
+ if (options.portalUrl) {
2611
+ validateFunctionParams([
2612
+ { paramName: "portalUrl", input: options.portalUrl, isString: true }
2613
+ ], "the constructor");
2614
+ }
1638
2615
  if (options.customSharePageUrl) {
1639
2616
  validateFunctionParams([
1640
2617
  { paramName: "customSharePageUrl", input: options.customSharePageUrl, isString: true }
@@ -1657,7 +2634,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1657
2634
  Intl.getCanonicalLocales(options.preferredLocale);
1658
2635
  return true;
1659
2636
  } catch (error) {
1660
- logger8.info("Failed to canonicalize locale", error);
2637
+ logger10.info("Failed to canonicalize locale", error);
1661
2638
  return false;
1662
2639
  }
1663
2640
  }
@@ -1671,10 +2648,21 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1671
2648
  proofRequestInstance.sessionId = data.sessionId;
1672
2649
  proofRequestInstance.resolvedProviderVersion = data.resolvedProviderVersion;
1673
2650
  proofRequestInstance.context.reclaimSessionId = data.sessionId;
2651
+ if (options == null ? void 0 : options.acceptTeeAttestation) {
2652
+ const wallet = new import_ethers5.ethers.Wallet(appSecret);
2653
+ const nonceData = `${applicationId}:${data.sessionId}:${proofRequestInstance.timeStamp}`;
2654
+ const nonceMsg = import_ethers5.ethers.getBytes(import_ethers5.ethers.keccak256(new TextEncoder().encode(nonceData)));
2655
+ const nonceSignature = yield wallet.signMessage(nonceMsg);
2656
+ proofRequestInstance.setAttestationContext(nonceSignature, {
2657
+ applicationId,
2658
+ sessionId: data.sessionId,
2659
+ timestamp: proofRequestInstance.timeStamp
2660
+ });
2661
+ }
1674
2662
  return proofRequestInstance;
1675
2663
  } catch (error) {
1676
2664
  console.error(error);
1677
- logger8.info("Failed to initialize ReclaimProofRequest", error);
2665
+ logger10.info("Failed to initialize ReclaimProofRequest", error);
1678
2666
  throw new InitError("Failed to initialize ReclaimProofRequest", error);
1679
2667
  }
1680
2668
  });
@@ -1791,7 +2779,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1791
2779
  Intl.getCanonicalLocales(options.preferredLocale);
1792
2780
  return true;
1793
2781
  } catch (error) {
1794
- logger8.info("Failed to canonicalize locale", error);
2782
+ logger10.info("Failed to canonicalize locale", error);
1795
2783
  return false;
1796
2784
  }
1797
2785
  }
@@ -1800,6 +2788,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1800
2788
  const proofRequestInstance = new _ReclaimProofRequest(applicationId, providerId, options);
1801
2789
  proofRequestInstance.sessionId = sessionId;
1802
2790
  proofRequestInstance.context = context;
2791
+ proofRequestInstance.setAttestationContext(context == null ? void 0 : context.attestationNonce, context == null ? void 0 : context.attestationNonceData);
1803
2792
  proofRequestInstance.parameters = parameters;
1804
2793
  proofRequestInstance.appCallbackUrl = appCallbackUrl;
1805
2794
  proofRequestInstance.redirectUrl = redirectUrl;
@@ -1815,7 +2804,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1815
2804
  proofRequestInstance.cancelRedirectUrlOptions = cancelRedirectUrlOptions;
1816
2805
  return proofRequestInstance;
1817
2806
  } catch (error) {
1818
- logger8.info("Failed to parse JSON string in fromJsonString:", error);
2807
+ logger10.info("Failed to parse JSON string in fromJsonString:", error);
1819
2808
  throw new InvalidParamError("Invalid JSON string provided to fromJsonString");
1820
2809
  }
1821
2810
  });
@@ -1856,11 +2845,11 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1856
2845
  *
1857
2846
  * @param url - The URL where users should be redirected after successful proof generation
1858
2847
  * @param method - The redirection method that should be used for redirection. Allowed options: `GET`, and `POST`.
1859
- * `POST` form redirection is only supported in In-Browser SDK.
2848
+ * `POST` form redirection is only supported in Portal flow.
1860
2849
  * @param body - List of name-value pairs to be sent as the body of the form request.
1861
2850
  * `When `method` is set to `POST`, `body` will be sent with 'application/x-www-form-urlencoded' content type.
1862
2851
  * When `method` is set to `GET`, if `body` is set then `body` will be sent as query parameters.
1863
- * Sending `body` on redirection is only supported in In-Browser SDK.
2852
+ * Sending `body` on redirection is only supported in Portal flow.
1864
2853
  *
1865
2854
  * @throws {InvalidParamError} When URL is invalid
1866
2855
  *
@@ -1922,11 +2911,11 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1922
2911
  *
1923
2912
  * @param url - The URL where users should be redirected after an error which aborts the verification process
1924
2913
  * @param method - The redirection method that should be used for redirection. Allowed options: `GET`, and `POST`.
1925
- * `POST` form redirection is only supported in In-Browser SDK.
2914
+ * `POST` form redirection is only supported in Portal flow.
1926
2915
  * @param body - List of name-value pairs to be sent as the body of the form request.
1927
2916
  * When `method` is set to `POST`, `body` will be sent with 'application/x-www-form-urlencoded' content type.
1928
2917
  * When `method` is set to `GET`, if `body` is set then `body` will be sent as query parameters.
1929
- * Sending `body` on redirection is only supported in In-Browser SDK.
2918
+ * Sending `body` on redirection is only supported in Portal flow.
1930
2919
  * @throws {InvalidParamError} When URL is invalid
1931
2920
  *
1932
2921
  * @example
@@ -1976,9 +2965,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
1976
2965
  try {
1977
2966
  validateModalOptions(options, "setModalOptions");
1978
2967
  this.modalOptions = __spreadValues(__spreadValues({}, this.modalOptions), options);
1979
- logger8.info("Modal options set successfully");
2968
+ logger10.info("Modal options set successfully");
1980
2969
  } catch (error) {
1981
- logger8.info("Error setting modal options:", error);
2970
+ logger10.info("Error setting modal options:", error);
1982
2971
  throw new SetParamsError("Error setting modal options", error);
1983
2972
  }
1984
2973
  }
@@ -2006,8 +2995,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2006
2995
  { input: context, paramName: "context", isString: false }
2007
2996
  ], "setJsonContext");
2008
2997
  this.context = JSON.parse(canonicalStringify(__spreadProps(__spreadValues({}, context), { reclaimSessionId: this.sessionId })));
2998
+ this.applyAttestationContext();
2009
2999
  } catch (error) {
2010
- logger8.info("Error setting context", error);
3000
+ logger10.info("Error setting context", error);
2011
3001
  throw new SetContextError("Error setting context", error);
2012
3002
  }
2013
3003
  }
@@ -2037,8 +3027,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2037
3027
  { input: message, paramName: "message", isString: true }
2038
3028
  ], "setContext");
2039
3029
  this.context = { contextAddress: address, contextMessage: message, reclaimSessionId: this.sessionId };
3030
+ this.applyAttestationContext();
2040
3031
  } catch (error) {
2041
- logger8.info("Error setting context", error);
3032
+ logger10.info("Error setting context", error);
2042
3033
  throw new SetContextError("Error setting context", error);
2043
3034
  }
2044
3035
  }
@@ -2073,7 +3064,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2073
3064
  validateParameters(params);
2074
3065
  this.parameters = __spreadValues(__spreadValues({}, this.parameters), params);
2075
3066
  } catch (error) {
2076
- logger8.info("Error Setting Params:", error);
3067
+ logger10.info("Error Setting Params:", error);
2077
3068
  throw new SetParamsError("Error setting params", error);
2078
3069
  }
2079
3070
  }
@@ -2097,7 +3088,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2097
3088
  validateFunctionParams([{ input: this.sessionId, paramName: "sessionId", isString: true }], "getAppCallbackUrl");
2098
3089
  return this.appCallbackUrl || `${constants.DEFAULT_RECLAIM_CALLBACK_URL}${this.sessionId}`;
2099
3090
  } catch (error) {
2100
- logger8.info("Error getting app callback url", error);
3091
+ logger10.info("Error getting app callback url", error);
2101
3092
  throw new GetAppCallbackUrlError("Error getting app callback url", error);
2102
3093
  }
2103
3094
  }
@@ -2121,7 +3112,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2121
3112
  validateFunctionParams([{ input: this.sessionId, paramName: "sessionId", isString: true }], "getCancelCallbackUrl");
2122
3113
  return this.cancelCallbackUrl || `${constants.DEFAULT_RECLAIM_CANCEL_CALLBACK_URL}${this.sessionId}`;
2123
3114
  } catch (error) {
2124
- logger8.info("Error getting cancel callback url", error);
3115
+ logger10.info("Error getting cancel callback url", error);
2125
3116
  throw new GetAppCallbackUrlError("Error getting cancel callback url", error);
2126
3117
  }
2127
3118
  }
@@ -2144,7 +3135,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2144
3135
  validateFunctionParams([{ input: this.sessionId, paramName: "sessionId", isString: true }], "getStatusUrl");
2145
3136
  return `${constants.DEFAULT_RECLAIM_STATUS_URL}${this.sessionId}`;
2146
3137
  } catch (error) {
2147
- logger8.info("Error fetching Status Url", error);
3138
+ logger10.info("Error fetching Status Url", error);
2148
3139
  throw new GetStatusUrlError("Error fetching status url", error);
2149
3140
  }
2150
3141
  }
@@ -2174,25 +3165,25 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2174
3165
  try {
2175
3166
  validateFunctionParams([{ input: signature, paramName: "signature", isString: true }], "setSignature");
2176
3167
  this.signature = signature;
2177
- logger8.info(`Signature set successfully for applicationId: ${this.applicationId}`);
3168
+ logger10.info(`Signature set successfully for applicationId: ${this.applicationId}`);
2178
3169
  } catch (error) {
2179
- logger8.info("Error setting signature", error);
3170
+ logger10.info("Error setting signature", error);
2180
3171
  throw new SetSignatureError("Error setting signature", error);
2181
3172
  }
2182
3173
  }
2183
3174
  generateSignature(applicationSecret) {
2184
3175
  return __async(this, null, function* () {
2185
3176
  try {
2186
- const wallet = new import_ethers4.ethers.Wallet(applicationSecret);
3177
+ const wallet = new import_ethers5.ethers.Wallet(applicationSecret);
2187
3178
  const canonicalData = (0, import_canonicalize3.default)({ providerId: this.providerId, timestamp: this.timeStamp });
2188
3179
  if (!canonicalData) {
2189
3180
  throw new SignatureGeneratingError("Failed to canonicalize data for signing.");
2190
3181
  }
2191
- const messageHash = import_ethers4.ethers.keccak256(new TextEncoder().encode(canonicalData));
2192
- return yield wallet.signMessage(import_ethers4.ethers.getBytes(messageHash));
3182
+ const messageHash = import_ethers5.ethers.keccak256(new TextEncoder().encode(canonicalData));
3183
+ return yield wallet.signMessage(import_ethers5.ethers.getBytes(messageHash));
2193
3184
  } catch (err) {
2194
- logger8.info(`Error generating proof request for applicationId: ${this.applicationId}, providerId: ${this.providerId}, signature: ${this.signature}, timeStamp: ${this.timeStamp}`, err);
2195
- throw new SignatureGeneratingError(`Error generating signature for applicationSecret: ${applicationSecret}`);
3185
+ logger10.info(`Error generating proof request for applicationId: ${this.applicationId}, providerId: ${this.providerId}, timeStamp: ${this.timeStamp}`);
3186
+ throw new SignatureGeneratingError(`Error generating signature for applicationId: ${this.applicationId}`);
2196
3187
  }
2197
3188
  });
2198
3189
  }
@@ -2202,12 +3193,97 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2202
3193
  this.intervals.delete(this.sessionId);
2203
3194
  }
2204
3195
  }
3196
+ setAttestationContext(nonce, data) {
3197
+ if (!nonce || !data) {
3198
+ return;
3199
+ }
3200
+ this.attestationNonce = nonce;
3201
+ this.attestationNonceData = data;
3202
+ this.applyAttestationContext();
3203
+ }
3204
+ applyAttestationContext() {
3205
+ if (!this.attestationNonce || !this.attestationNonceData) {
3206
+ return;
3207
+ }
3208
+ this.context = __spreadProps(__spreadValues({}, this.context), {
3209
+ attestationNonce: this.attestationNonce,
3210
+ attestationNonceData: this.attestationNonceData
3211
+ });
3212
+ }
3213
+ encodeTemplateData(templateData) {
3214
+ let template = encodeURIComponent(JSON.stringify(templateData));
3215
+ template = replaceAll(template, "(", "%28");
3216
+ template = replaceAll(template, ")", "%29");
3217
+ return template;
3218
+ }
2205
3219
  buildSharePageUrl(template) {
2206
- const baseUrl = "https://share.reclaimprotocol.org/verify";
2207
- if (this.customSharePageUrl) {
2208
- return `${this.customSharePageUrl}/?template=${template}`;
3220
+ return `${this.appSharePageUrl}/?template=${template}`;
3221
+ }
3222
+ openPortalTab(templateData, preOpenedTab) {
3223
+ return __async(this, null, function* () {
3224
+ const newTab = preOpenedTab != null ? preOpenedTab : window.open("about:blank", "_blank");
3225
+ const link = yield createLinkWithTemplateData(templateData, this.customSharePageUrl);
3226
+ logger10.info("Opening portal in new tab: " + link);
3227
+ if (newTab) {
3228
+ this.portalTab = newTab;
3229
+ newTab.location = link;
3230
+ setTimeout(() => {
3231
+ try {
3232
+ if (newTab.location.href === "about:blank") {
3233
+ newTab.close();
3234
+ this.portalTab = void 0;
3235
+ window.open(link, "_blank");
3236
+ }
3237
+ } catch (_) {
3238
+ }
3239
+ }, 500);
3240
+ }
3241
+ });
3242
+ }
3243
+ closePortalTab() {
3244
+ var _a;
3245
+ try {
3246
+ (_a = this.portalTab) == null ? void 0 : _a.close();
3247
+ } catch (_) {
2209
3248
  }
2210
- return `${baseUrl}/?template=${template}`;
3249
+ this.portalTab = void 0;
3250
+ }
3251
+ embedPortalIframe(templateData, target) {
3252
+ return __async(this, null, function* () {
3253
+ let link = yield createLinkWithTemplateData(templateData, this.customSharePageUrl);
3254
+ const separator = link.includes("?") ? "&" : "?";
3255
+ link = `${link}${separator}embedded=true`;
3256
+ logger10.info("Embedding portal in iframe: " + link);
3257
+ this.closeEmbeddedFlow();
3258
+ const iframe = document.createElement("iframe");
3259
+ iframe.src = link;
3260
+ iframe.style.width = "100%";
3261
+ iframe.style.height = "100%";
3262
+ iframe.style.border = "none";
3263
+ iframe.setAttribute("allow", "clipboard-write");
3264
+ iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms");
3265
+ target.appendChild(iframe);
3266
+ this.portalIframe = iframe;
3267
+ });
3268
+ }
3269
+ /**
3270
+ * Closes the embedded portal iframe and stops the session polling.
3271
+ *
3272
+ * Call this to programmatically cancel the embedded verification flow
3273
+ * that was started with `triggerReclaimFlow({ target: element })`.
3274
+ * Also called automatically when verification succeeds or fails.
3275
+ *
3276
+ * @example
3277
+ * ```typescript
3278
+ * proofRequest.closeEmbeddedFlow();
3279
+ * ```
3280
+ */
3281
+ closeEmbeddedFlow() {
3282
+ if (this.portalIframe) {
3283
+ this.portalIframe.remove();
3284
+ this.portalIframe = void 0;
3285
+ }
3286
+ this.clearInterval();
2211
3287
  }
2212
3288
  /**
2213
3289
  * Exports the Reclaim proof verification request as a JSON string
@@ -2261,13 +3337,15 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2261
3337
  });
2262
3338
  }
2263
3339
  /**
2264
- * Generates and returns the request URL for proof verification
3340
+ * Generates and returns the request URL for proof verification.
3341
+ *
3342
+ * Defaults to portal mode. Pass `{ verificationMode: 'app' }` for native app flow URLs.
2265
3343
  *
2266
- * This URL can be shared with users to initiate the proof generation process.
2267
- * The URL format varies based on device type:
2268
- * - Mobile iOS: Returns App Clip URL (if useAppClip is enabled)
2269
- * - Mobile Android: Returns Instant App URL (if useAppClip is enabled)
2270
- * - Desktop/Other: Returns standard verification URL
3344
+ * - Portal mode (default): returns portal URL on all platforms
3345
+ * - App mode: returns share page URL on all platforms
3346
+ * - App mode + `useAppClip: true` on iOS: returns App Clip URL instead
3347
+ *
3348
+ * Falls back to `launchOptions` set at init time if not passed at call time.
2271
3349
  *
2272
3350
  * @param launchOptions - Optional launch configuration to override default behavior
2273
3351
  * @returns Promise<string> - The generated request URL
@@ -2275,105 +3353,155 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2275
3353
  *
2276
3354
  * @example
2277
3355
  * ```typescript
2278
- * const requestUrl = await proofRequest.getRequestUrl();
2279
- * // Share this URL with users or display as QR code
3356
+ * // Portal URL (default)
3357
+ * const url = await proofRequest.getRequestUrl();
3358
+ *
3359
+ * // Verifier app flow URL
3360
+ * const url = await proofRequest.getRequestUrl({ verificationMode: 'app' });
2280
3361
  * ```
2281
3362
  */
2282
3363
  getRequestUrl(launchOptions) {
2283
3364
  return __async(this, null, function* () {
2284
3365
  var _a, _b, _c;
2285
3366
  const options = launchOptions || ((_a = this.options) == null ? void 0 : _a.launchOptions) || {};
2286
- logger8.info("Creating Request Url");
3367
+ const mode = (_b = options.verificationMode) != null ? _b : "portal";
3368
+ logger10.info("Creating Request Url");
2287
3369
  if (!this.signature) {
2288
3370
  throw new SignatureNotFoundError("Signature is not set.");
2289
3371
  }
2290
3372
  try {
2291
3373
  const templateData = this.getTemplateData();
2292
3374
  yield updateSession(this.sessionId, "SESSION_STARTED" /* SESSION_STARTED */);
2293
- const deviceType = getDeviceType();
2294
- if (((_b = this.options) == null ? void 0 : _b.useAppClip) && deviceType === "mobile" /* MOBILE */) {
2295
- let template = encodeURIComponent(JSON.stringify(templateData));
2296
- template = replaceAll(template, "(", "%28");
2297
- template = replaceAll(template, ")", "%29");
2298
- const isIos = getMobileDeviceType() === "ios" /* IOS */;
2299
- if (!isIos) {
2300
- let instantAppUrl = this.buildSharePageUrl(template);
2301
- const isDeferredDeeplinksFlowEnabled = (_c = options.canUseDeferredDeepLinksFlow) != null ? _c : false;
2302
- if (isDeferredDeeplinksFlowEnabled) {
2303
- instantAppUrl = instantAppUrl.replace("/verifier", "/link");
2304
- }
2305
- logger8.info("Instant App Url created successfully: " + instantAppUrl);
2306
- return instantAppUrl;
2307
- } else {
3375
+ if (mode === "app") {
3376
+ const template = this.encodeTemplateData(templateData);
3377
+ if (((_c = this.options) == null ? void 0 : _c.useAppClip) && getDeviceType() === "mobile" /* MOBILE */ && getMobileDeviceType() === "ios" /* IOS */) {
2308
3378
  const appClipUrl = this.customAppClipUrl ? `${this.customAppClipUrl}&template=${template}` : `https://appclip.apple.com/id?p=org.reclaimprotocol.app.clip&template=${template}`;
2309
- logger8.info("App Clip Url created successfully: " + appClipUrl);
3379
+ logger10.info("App Clip Url created successfully: " + appClipUrl);
2310
3380
  return appClipUrl;
2311
3381
  }
2312
- } else {
2313
- const link = yield createLinkWithTemplateData(templateData, this.customSharePageUrl);
2314
- logger8.info("Request Url created successfully: " + link);
2315
- return link;
3382
+ const sharePageUrl = yield createLinkWithTemplateData(templateData, this.appSharePageUrl);
3383
+ logger10.info("Share page Url created successfully: " + sharePageUrl);
3384
+ return sharePageUrl;
2316
3385
  }
3386
+ const link = yield createLinkWithTemplateData(templateData, this.customSharePageUrl);
3387
+ logger10.info("Request Url created successfully: " + link);
3388
+ return link;
2317
3389
  } catch (error) {
2318
- logger8.info("Error creating Request Url:", error);
3390
+ logger10.info("Error creating Request Url:", error);
2319
3391
  throw error;
2320
3392
  }
2321
3393
  });
2322
3394
  }
2323
3395
  /**
2324
- * Triggers the appropriate Reclaim verification flow based on device type and configuration
3396
+ * Triggers the appropriate Reclaim verification flow based on device type and configuration.
2325
3397
  *
2326
- * This method automatically detects the device type and initiates the optimal verification flow:
2327
- * - Desktop with browser extension: Triggers extension flow
2328
- * - Desktop without extension: Shows QR code modal
2329
- * - Mobile Android: Redirects to Instant App
2330
- * - Mobile iOS: Redirects to App Clip
3398
+ * Defaults to portal mode (remote browser verification). Pass `{ verificationMode: 'app' }`
3399
+ * for verifier app flow via the share page.
3400
+ *
3401
+ * - **Embedded iframe**: Pass `{ target: element }` to embed the portal inside a DOM element instead of a new tab
3402
+ * - Desktop: browser extension takes priority in both modes
3403
+ * - Desktop portal mode (no extension): opens portal in new tab
3404
+ * - Desktop app mode (no extension): shows QR code modal with share page URL
3405
+ * - Mobile portal mode: opens portal in new tab
3406
+ * - Mobile app mode: opens share page (or App Clip on iOS if `useAppClip` is `true`)
2331
3407
  *
2332
3408
  * @param launchOptions - Optional launch configuration to override default behavior
2333
- * @returns Promise<void>
3409
+ * @returns Promise<FlowHandle> - Handle to control the flow (close, access iframe)
2334
3410
  * @throws {SignatureNotFoundError} When signature is not set
2335
3411
  *
2336
3412
  * @example
2337
3413
  * ```typescript
2338
- * await proofRequest.triggerReclaimFlow();
2339
- * // The appropriate verification method will be triggered automatically
3414
+ * // Portal flow (default) — opens in new tab
3415
+ * const handle = await proofRequest.triggerReclaimFlow();
3416
+ * handle.tab; // Window reference to the opened tab
3417
+ * handle.close(); // close tab and stop polling
3418
+ *
3419
+ * // Embed portal in an iframe inside a DOM element
3420
+ * const handle = await proofRequest.triggerReclaimFlow({ target: document.getElementById('reclaim-container') });
3421
+ * handle.iframe; // HTMLIFrameElement reference
3422
+ * handle.close(); // remove iframe and stop polling
3423
+ *
3424
+ * // Verifier app flow
3425
+ * await proofRequest.triggerReclaimFlow({ verificationMode: 'app' });
3426
+ *
3427
+ * // App Clip on iOS (requires useAppClip: true at init)
3428
+ * const request = await ReclaimProofRequest.init(APP_ID, SECRET, PROVIDER, { useAppClip: true });
3429
+ * await request.triggerReclaimFlow({ verificationMode: 'app' });
3430
+ *
3431
+ * // Can also set verificationMode at init time via launchOptions
3432
+ * const request = await ReclaimProofRequest.init(APP_ID, SECRET, PROVIDER, {
3433
+ * launchOptions: { verificationMode: 'app' }
3434
+ * });
3435
+ * await request.triggerReclaimFlow(); // uses 'app' mode from init
2340
3436
  * ```
2341
3437
  */
2342
3438
  triggerReclaimFlow(launchOptions) {
2343
3439
  return __async(this, null, function* () {
2344
- var _a, _b;
3440
+ var _a, _b, _c, _d, _e;
2345
3441
  const options = launchOptions || ((_a = this.options) == null ? void 0 : _a.launchOptions) || {};
3442
+ const mode = (_b = options.verificationMode) != null ? _b : "portal";
2346
3443
  if (!this.signature) {
2347
3444
  throw new SignatureNotFoundError("Signature is not set.");
2348
3445
  }
2349
3446
  try {
2350
3447
  const templateData = this.getTemplateData();
2351
3448
  this.templateData = templateData;
2352
- logger8.info("Triggering Reclaim flow");
3449
+ logger10.info(`Triggering Reclaim flow (mode: ${mode})`);
2353
3450
  const deviceType = getDeviceType();
2354
3451
  updateSession(this.sessionId, "SESSION_STARTED" /* SESSION_STARTED */);
3452
+ if ("target" in options && !options.target) {
3453
+ logger10.warn("triggerReclaimFlow: target was provided but is null/undefined \u2014 falling back to default flow. Ensure the element exists in the DOM.");
3454
+ }
3455
+ if (options.target && mode === "portal") {
3456
+ yield this.embedPortalIframe(templateData, options.target);
3457
+ return {
3458
+ close: () => this.closeEmbeddedFlow(),
3459
+ iframe: this.portalIframe
3460
+ };
3461
+ }
2355
3462
  if (deviceType === "desktop" /* DESKTOP */) {
2356
- const extensionAvailable = yield this.isBrowserExtensionAvailable();
2357
- if (((_b = this.options) == null ? void 0 : _b.useBrowserExtension) && extensionAvailable) {
2358
- logger8.info("Triggering browser extension flow");
2359
- this.triggerBrowserExtensionFlow();
2360
- return;
3463
+ if ((_c = this.options) == null ? void 0 : _c.useBrowserExtension) {
3464
+ const extensionAvailable = yield this.isBrowserExtensionAvailable();
3465
+ if (extensionAvailable) {
3466
+ logger10.info("Triggering browser extension flow");
3467
+ this.triggerBrowserExtensionFlow();
3468
+ return {
3469
+ close: () => {
3470
+ this.clearInterval();
3471
+ }
3472
+ };
3473
+ }
3474
+ }
3475
+ if (mode === "portal") {
3476
+ yield this.openPortalTab(templateData);
2361
3477
  } else {
2362
- logger8.info("Browser extension not available, showing QR code modal");
3478
+ logger10.info("Showing QR code modal with share page URL");
2363
3479
  yield this.showQRCodeModal();
2364
3480
  }
2365
3481
  } else if (deviceType === "mobile" /* MOBILE */) {
2366
- const mobileDeviceType = getMobileDeviceType();
2367
- if (mobileDeviceType === "android" /* ANDROID */) {
2368
- logger8.info("Redirecting to Android instant app");
2369
- yield this.redirectToInstantApp(options);
2370
- } else if (mobileDeviceType === "ios" /* IOS */) {
2371
- logger8.info("Redirecting to iOS app clip");
2372
- this.redirectToAppClip();
3482
+ if (mode === "app") {
3483
+ if (((_d = this.options) == null ? void 0 : _d.useAppClip) && getMobileDeviceType() === "ios" /* IOS */) {
3484
+ logger10.info("Redirecting to iOS app clip");
3485
+ this.redirectToAppClip();
3486
+ } else {
3487
+ logger10.info("Redirecting to share page");
3488
+ yield this.redirectToInstantApp(options);
3489
+ }
3490
+ } else {
3491
+ yield this.openPortalTab(templateData);
2373
3492
  }
2374
3493
  }
3494
+ return {
3495
+ close: () => {
3496
+ var _a2;
3497
+ this.closePortalTab();
3498
+ this.closeEmbeddedFlow();
3499
+ (_a2 = this.modal) == null ? void 0 : _a2.close();
3500
+ },
3501
+ tab: (_e = this.portalTab) != null ? _e : void 0
3502
+ };
2375
3503
  } catch (error) {
2376
- logger8.info("Error triggering Reclaim flow:", error);
3504
+ logger10.info("Error triggering Reclaim flow:", error);
2377
3505
  throw error;
2378
3506
  }
2379
3507
  });
@@ -2421,7 +3549,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2421
3549
  window.postMessage(message, "*");
2422
3550
  });
2423
3551
  } catch (error) {
2424
- logger8.info("Error checking Reclaim extension installed:", error);
3552
+ logger10.info("Error checking Reclaim extension installed:", error);
2425
3553
  return false;
2426
3554
  }
2427
3555
  });
@@ -2434,16 +3562,16 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2434
3562
  extensionID: this.extensionID
2435
3563
  };
2436
3564
  window.postMessage(message, "*");
2437
- logger8.info("Browser extension flow triggered");
3565
+ logger10.info("Browser extension flow triggered");
2438
3566
  }
2439
3567
  showQRCodeModal() {
2440
3568
  return __async(this, null, function* () {
2441
3569
  try {
2442
- const requestUrl = yield createLinkWithTemplateData(this.templateData, this.customSharePageUrl);
3570
+ const requestUrl = yield createLinkWithTemplateData(this.templateData, this.appSharePageUrl);
2443
3571
  this.modal = new QRCodeModal(this.modalOptions);
2444
3572
  yield this.modal.show(requestUrl);
2445
3573
  } catch (error) {
2446
- logger8.info("Error showing QR code modal:", error);
3574
+ logger10.info("Error showing QR code modal:", error);
2447
3575
  throw error;
2448
3576
  }
2449
3577
  });
@@ -2452,11 +3580,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2452
3580
  return __async(this, null, function* () {
2453
3581
  var _a;
2454
3582
  try {
2455
- let template = encodeURIComponent(JSON.stringify(this.templateData));
2456
- template = replaceAll(template, "(", "%28");
2457
- template = replaceAll(template, ")", "%29");
3583
+ const template = this.encodeTemplateData(this.templateData);
2458
3584
  let instantAppUrl = this.buildSharePageUrl(template);
2459
- logger8.info("Redirecting to Android instant app: " + instantAppUrl);
3585
+ logger10.info("Redirecting to Android instant app: " + instantAppUrl);
2460
3586
  const isDeferredDeeplinksFlowEnabled = (_a = options.canUseDeferredDeepLinksFlow) != null ? _a : false;
2461
3587
  if (isDeferredDeeplinksFlowEnabled) {
2462
3588
  instantAppUrl = instantAppUrl.replace("/verifier", "/link");
@@ -2506,40 +3632,58 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2506
3632
  }
2507
3633
  window.location.href = instantAppUrl;
2508
3634
  } catch (error) {
2509
- logger8.info("Error redirecting to instant app:", error);
3635
+ logger10.info("Error redirecting to instant app:", error);
2510
3636
  throw error;
2511
3637
  }
2512
3638
  });
2513
3639
  }
2514
3640
  redirectToAppClip() {
2515
3641
  try {
2516
- let template = encodeURIComponent(JSON.stringify(this.templateData));
2517
- template = replaceAll(template, "(", "%28");
2518
- template = replaceAll(template, ")", "%29");
3642
+ const template = this.encodeTemplateData(this.templateData);
2519
3643
  const appClipUrl = this.customAppClipUrl ? `${this.customAppClipUrl}&template=${template}` : `https://appclip.apple.com/id?p=org.reclaimprotocol.app.clip&template=${template}`;
2520
- logger8.info("Redirecting to iOS app clip: " + appClipUrl);
2521
- const verifierUrl = `https://share.reclaimprotocol.org/verifier/?template=${template}`;
3644
+ logger10.info("Redirecting to iOS app clip: " + appClipUrl);
3645
+ const verifierUrl = `${this.appSharePageUrl}/?template=${template}`;
2522
3646
  window.location.href = appClipUrl;
2523
3647
  setTimeout(() => {
2524
3648
  window.location.href = verifierUrl;
2525
3649
  }, 5 * 1e3);
2526
3650
  } catch (error) {
2527
- logger8.info("Error redirecting to app clip:", error);
3651
+ logger10.info("Error redirecting to app clip:", error);
2528
3652
  throw error;
2529
3653
  }
2530
3654
  }
3655
+ /**
3656
+ * Returns the provider id and exact version of the provider that was used in the verification session of this request.
3657
+ *
3658
+ * This can be provided as a config parameter to the `verifyProof` function to verify the proof.
3659
+ *
3660
+ * See also:
3661
+ * * `verifyProof()` - Verifies a proof against the expected provider configuration.
3662
+ * * `getProviderHashRequirements()` - An alternative of this function to get the expected hashes for a provider version by providing providerId and exactProviderVersionString. The result can be provided in verifyProof function's `config` parameter for proof validation.
3663
+ * * `getProviderHashRequirementsFromSpec()` - An alternative of this function to get the expected hashes from a provider spec. The result can be provided in verifyProof function's `config` parameter for proof validation.
3664
+ */
3665
+ getProviderVersion() {
3666
+ var _a, _b;
3667
+ const exactProviderVersionString = (_a = this.resolvedProviderVersion) != null ? _a : "";
3668
+ return {
3669
+ providerId: this.providerId,
3670
+ providerVersion: exactProviderVersionString,
3671
+ allowedTags: ((_b = this.options) == null ? void 0 : _b.acceptAiProviders) ? ["ai"] : []
3672
+ };
3673
+ }
2531
3674
  /**
2532
3675
  * Fetches the provider config that was used for this session and returns the hash requirements
2533
3676
  *
2534
3677
  * See also:
3678
+ * * `verifyProof()` - Verifies a proof against the expected provider configuration.
2535
3679
  * * `fetchProviderHashRequirementsBy()` - An alternative of this function to get the expected hashes for a provider version by providing providerId and exactProviderVersionString. The result can be provided in verifyProof function's `config` parameter for proof validation.
2536
3680
  * * `getProviderHashRequirementsFromSpec()` - An alternative of this function to get the expected hashes from a provider spec. The result can be provided in verifyProof function's `config` parameter for proof validation.
2537
3681
  *
2538
- * @returns A promise that resolves to a ProviderHashRequirementsConfig
3682
+ * @returns A promise that resolves to a `ProviderHashRequirementsConfig` or `ProviderHashRequirementsConfig[]`
2539
3683
  */
2540
- getProviderHashRequirements() {
3684
+ getProviderHashRequirements(proofs, allowedTags) {
2541
3685
  var _a;
2542
- return fetchProviderHashRequirementsBy(this.providerId, (_a = this.resolvedProviderVersion) != null ? _a : "");
3686
+ return fetchProviderHashRequirementsBy(this.providerId, (_a = this.resolvedProviderVersion) != null ? _a : "", allowedTags, proofs);
2543
3687
  }
2544
3688
  /**
2545
3689
  * Starts the proof request session and monitors for proof submission
@@ -2584,13 +3728,13 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2584
3728
  return __async(this, arguments, function* ({ onSuccess, onError }) {
2585
3729
  if (!this.sessionId) {
2586
3730
  const message = "Session can't be started due to undefined value of sessionId";
2587
- logger8.info(message);
3731
+ logger10.info(message);
2588
3732
  throw new SessionNotStartedError(message);
2589
3733
  }
2590
- logger8.info("Starting session");
3734
+ logger10.info("Starting session");
2591
3735
  const sessionUpdatePollingInterval = 3 * 1e3;
2592
3736
  const interval = setInterval(() => __async(this, null, function* () {
2593
- var _a, _b, _c;
3737
+ var _a, _b, _c, _d, _e;
2594
3738
  try {
2595
3739
  const statusUrlResponse = yield fetchStatusUrl(this.sessionId);
2596
3740
  if (!statusUrlResponse.session) return;
@@ -2602,7 +3746,8 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2602
3746
  if (!this.lastFailureTime) {
2603
3747
  this.lastFailureTime = currentTime;
2604
3748
  } else if (currentTime - this.lastFailureTime >= this.FAILURE_TIMEOUT) {
2605
- throw new ProviderFailedError("Proof generation failed - timeout reached");
3749
+ const errorMessage = ((_a = statusUrlResponse.session.error) == null ? void 0 : _a.message) || "Proof generation failed - timeout reached";
3750
+ throw new ProviderFailedError(errorMessage);
2606
3751
  }
2607
3752
  return;
2608
3753
  }
@@ -2614,9 +3759,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2614
3759
  if (statusUrlResponse.session.proofs && statusUrlResponse.session.proofs.length > 0) {
2615
3760
  const proofs = statusUrlResponse.session.proofs;
2616
3761
  if (this.claimCreationType === "createClaim" /* STANDALONE */) {
2617
- const verified = yield verifyProof(proofs, yield this.getProviderHashRequirements());
3762
+ const { isVerified: verified } = yield verifyProof(proofs, this.getProviderVersion());
2618
3763
  if (!verified) {
2619
- logger8.info(`Proofs not verified: ${JSON.stringify(proofs)}`);
3764
+ logger10.info(`Proofs not verified: count=${proofs == null ? void 0 : proofs.length}`);
2620
3765
  throw new ProofNotVerifiedError();
2621
3766
  }
2622
3767
  }
@@ -2626,18 +3771,23 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2626
3771
  onSuccess(proofs);
2627
3772
  }
2628
3773
  this.clearInterval();
2629
- (_a = this.modal) == null ? void 0 : _a.close();
3774
+ (_b = this.modal) == null ? void 0 : _b.close();
3775
+ this.closePortalTab();
3776
+ this.closeEmbeddedFlow();
2630
3777
  }
2631
3778
  } else {
2632
3779
  if (statusUrlResponse.session.statusV2 === "PROOF_SUBMISSION_FAILED" /* PROOF_SUBMISSION_FAILED */) {
2633
- throw new ProofSubmissionFailedError();
3780
+ const errorMessage = ((_c = statusUrlResponse.session.error) == null ? void 0 : _c.message) || "Proof submission failed";
3781
+ throw new ProofSubmissionFailedError(errorMessage);
2634
3782
  }
2635
3783
  if (statusUrlResponse.session.statusV2 === "PROOF_SUBMITTED" /* PROOF_SUBMITTED */ || statusUrlResponse.session.statusV2 === "AI_PROOF_SUBMITTED" /* AI_PROOF_SUBMITTED */) {
2636
3784
  if (onSuccess) {
2637
3785
  onSuccess([]);
2638
3786
  }
2639
3787
  this.clearInterval();
2640
- (_b = this.modal) == null ? void 0 : _b.close();
3788
+ (_d = this.modal) == null ? void 0 : _d.close();
3789
+ this.closePortalTab();
3790
+ this.closeEmbeddedFlow();
2641
3791
  }
2642
3792
  }
2643
3793
  } catch (e) {
@@ -2645,7 +3795,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2645
3795
  onError(e);
2646
3796
  }
2647
3797
  this.clearInterval();
2648
- (_c = this.modal) == null ? void 0 : _c.close();
3798
+ (_e = this.modal) == null ? void 0 : _e.close();
3799
+ this.closePortalTab();
3800
+ this.closeEmbeddedFlow();
2649
3801
  }
2650
3802
  }), sessionUpdatePollingInterval);
2651
3803
  this.intervals.set(this.sessionId, interval);
@@ -2667,7 +3819,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2667
3819
  closeModal() {
2668
3820
  if (this.modal) {
2669
3821
  this.modal.close();
2670
- logger8.info("Modal closed by user");
3822
+ logger10.info("Modal closed by user");
2671
3823
  }
2672
3824
  }
2673
3825
  /**
@@ -2688,14 +3840,16 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2688
3840
  // Annotate the CommonJS export names for ESM import in node:
2689
3841
  0 && (module.exports = {
2690
3842
  ReclaimProofRequest,
3843
+ TeeVerificationError,
2691
3844
  assertValidProofsByHash,
2692
3845
  assertValidateProof,
2693
3846
  assertVerifiedProof,
2694
3847
  clearDeviceCache,
2695
3848
  createLinkWithTemplateData,
2696
- fetchProviderConfig,
3849
+ fetchProviderConfigs,
2697
3850
  fetchProviderHashRequirementsBy,
2698
3851
  fetchStatusUrl,
3852
+ generateSpecsFromRequestSpecTemplate,
2699
3853
  getAttestors,
2700
3854
  getDeviceType,
2701
3855
  getHttpProviderClaimParamsFromProof,
@@ -2708,8 +3862,11 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2708
3862
  isHttpProviderClaimParams,
2709
3863
  isMobileDevice,
2710
3864
  recoverSignersOfSignedClaim,
3865
+ takePairsWhereValueIsArray,
3866
+ takeTemplateParametersFromProofs,
2711
3867
  transformForOnchain,
2712
3868
  updateSession,
2713
- verifyProof
3869
+ verifyProof,
3870
+ verifyTeeAttestation
2714
3871
  });
2715
3872
  //# sourceMappingURL=index.js.map