@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/README.md CHANGED
@@ -99,7 +99,7 @@ function App() {
99
99
  setProofs(proofs);
100
100
  }
101
101
  },
102
- onFailure: (error) => {
102
+ onError: (error) => {
103
103
  console.error("Verification failed", error);
104
104
  },
105
105
  });
@@ -181,7 +181,7 @@ async function handleCreateClaim() {
181
181
  setProofs(proofs);
182
182
  }
183
183
  },
184
- onFailure: (error) => {
184
+ onError: (error) => {
185
185
  console.error("Verification failed", error);
186
186
  },
187
187
  });
@@ -193,17 +193,57 @@ async function handleCreateClaim() {
193
193
 
194
194
  ### How triggerReclaimFlow() Works
195
195
 
196
- The `triggerReclaimFlow()` method automatically detects the user's environment and chooses the optimal verification method:
196
+ The `triggerReclaimFlow()` method supports two verification modes via `verificationMode`:
197
+
198
+ - **`'portal'` (default)**: Opens the portal URL for remote browser verification. Opens in a new tab by default, or embedded in an iframe when `target` is provided.
199
+ - **`'app'`**: Verifier app flow via the share page. Uses App Clip on iOS if `useAppClip` is `true`.
200
+
201
+ The method returns a `FlowHandle` that lets you close the flow programmatically:
202
+
203
+ ```javascript
204
+ // Portal flow (default) — opens in new tab
205
+ const handle = await reclaimProofRequest.triggerReclaimFlow();
206
+ handle.tab; // Window reference to the opened tab
207
+ handle.close(); // close tab and stop polling
208
+
209
+ // Embedded — portal loads inside a DOM element as an iframe
210
+ const handle = await reclaimProofRequest.triggerReclaimFlow({
211
+ target: document.getElementById('reclaim-container')
212
+ });
213
+ handle.iframe; // HTMLIFrameElement reference
214
+ handle.iframe?.style.height = '700px'; // customize the iframe
215
+ handle.close(); // remove iframe and stop polling
216
+
217
+ // Verifier app flow
218
+ const handle = await reclaimProofRequest.triggerReclaimFlow({ verificationMode: 'app' });
219
+ handle.close(); // stop polling
220
+ ```
197
221
 
198
222
  #### On Desktop Browsers:
199
223
 
200
- 1. **Browser Extension First**: If the Reclaim browser extension is installed, it will use the extension for a seamless in-browser verification experience.
201
- 2. **QR Code Fallback**: If the extension is not available, it automatically displays a QR code modal for mobile scanning.
224
+ 1. **Embedded mode**: If `target` is provided, the portal loads in an iframe inside the target element.
225
+ 2. **Browser Extension**: If the Reclaim browser extension is installed and no `target` is set, it will use the extension.
226
+ 3. **Portal mode** (no extension, no target): Opens the portal in a new tab.
227
+ 4. **App mode** (no extension): Shows QR code modal with share page URL.
228
+
229
+ #### On Mobile Devices (portal mode):
230
+
231
+ Opens the portal in a new tab, or in an iframe if `target` is provided.
202
232
 
203
- #### On Mobile Devices:
233
+ #### On Mobile Devices (app mode):
204
234
 
205
- 1. **iOS Devices**: Automatically redirects to the Reclaim App Clip for native iOS verification.
206
- 2. **Android Devices**: Automatically redirects to the Reclaim Instant App for native Android verification.
235
+ 1. **All platforms**: Redirects to the verifier app.
236
+ 2. **iOS with `useAppClip: true`**: Redirects to the Reclaim App Clip instead.
237
+
238
+ The same `verificationMode` option works with `getRequestUrl()`:
239
+
240
+ ```javascript
241
+ // Portal URL (default)
242
+ const url = await reclaimProofRequest.getRequestUrl();
243
+
244
+ // Verifier app URL
245
+ const url = await reclaimProofRequest.getRequestUrl({ verificationMode: 'app' });
246
+ ```
207
247
 
208
248
  ### Browser Extension Support
209
249
 
@@ -264,10 +304,10 @@ await reclaimProofRequest.triggerReclaimFlow();
264
304
  ### Benefits of the New Flow:
265
305
 
266
306
  1. **Platform Adaptive**: Automatically chooses the best verification method for each platform
267
- 2. **User-Friendly**: Provides the most seamless experience possible for each user
268
- 3. **Simplified Integration**: Single method call handles all verification scenarios
307
+ 2. **Embeddable**: Embed the portal directly in your page via iframe with `{ target: element }`
308
+ 3. **Controllable**: Returns a `FlowHandle` to close the flow or access the iframe at any time
269
309
  4. **Extension Support**: Leverages browser extension for desktop users when available
270
- 5. **Mobile Optimized**: Native app experiences on mobile devices
310
+ 5. **Mobile Optimized**: Verifier app experiences on mobile devices
271
311
 
272
312
  ## Step 6: Run your application
273
313
 
@@ -289,7 +329,7 @@ Your Reclaim SDK demo should now be running. Click the "Create Claim" button to
289
329
 
290
330
  4. **Verification**: The `onSuccess` is called when verification is successful, providing the proof data. When using a custom callback url, the proof is returned to the callback url and we get an empty array instead of a proof.
291
331
 
292
- 5. **Handling Failures**: The `onFailure` is called if verification fails, allowing you to handle errors gracefully.
332
+ 5. **Handling Failures**: The `onError` is called if verification fails, allowing you to handle errors gracefully.
293
333
 
294
334
  ## Advanced Configuration
295
335
 
@@ -324,17 +364,17 @@ Redirection with body:
324
364
 
325
365
  - **url**: The URL where users should be redirected after successful proof generation.
326
366
  - **method** (optional): The redirection method to use. Allowed options: `GET` (default) and `POST`.
327
- *Note: `POST` form redirection is only supported in In-Browser SDK.*
367
+ *Note: `POST` form redirection is only supported in Portal flow.*
328
368
  - **body** (optional): List of name-value pairs to be sent as the body of the form request.
329
369
  - When `method` is `POST`, `body` is sent with `application/x-www-form-urlencoded` content type.
330
370
  - When `method` is `GET`, if `body` is set, it is sent as query parameters.
331
- *Note: Sending `body` on redirection is only supported in In-Browser SDK.*
371
+ *Note: Sending `body` on redirection is only supported in Portal flow.*
332
372
 
333
373
  ```javascript
334
374
  reclaimProofRequest.setRedirectUrl(
335
375
  "https://example.com/redirect",
336
- "POST", // In-Browser SDK only
337
- [{ name: "foo", value: "bar" }] // In-Browser SDK only
376
+ "POST", // Portal flow only
377
+ [{ name: "foo", value: "bar" }] // Portal flow only
338
378
  );
339
379
  ```
340
380
 
@@ -350,17 +390,17 @@ Redirection with body:
350
390
 
351
391
  - **url**: The URL where users should be redirected after an error which aborts the verification process.
352
392
  - **method** (optional): The redirection method to use. Allowed options: `GET` (default) and `POST`.
353
- *Note: `POST` form redirection is only supported in In-Browser SDK.*
393
+ *Note: `POST` form redirection is only supported in Portal flow.*
354
394
  - **body** (optional): List of name-value pairs to be sent as the body of the form request.
355
395
  - When `method` is `POST`, `body` is sent with `application/x-www-form-urlencoded` content type.
356
396
  - When `method` is `GET`, if `body` is set, it is sent as query parameters.
357
- *Note: Sending `body` on redirection is only supported in In-Browser SDK.*
397
+ *Note: Sending `body` on redirection is only supported in Portal flow.*
358
398
 
359
399
  ```javascript
360
400
  reclaimProofRequest.setCancelRedirectUrl(
361
401
  "https://example.com/error-redirect",
362
- "POST", // In-Browser SDK only
363
- [{ name: "error_code", value: "1001" }] // In-Browser SDK only
402
+ "POST", // Portal flow only
403
+ [{ name: "error_code", value: "1001" }] // Portal flow only
364
404
  );
365
405
  ```
366
406
 
@@ -371,6 +411,7 @@ reclaimProofRequest.setCancelRedirectUrl(
371
411
 
372
412
  By default, proofs are sent as HTTP `POST` with `Content-Type` as `application/x-www-form-urlencoded`. Pass function argument `jsonProofResponse` as `true` to send proofs with `Content-Type` as `application/json`.
373
413
 
414
+ ```javascript
374
415
  reclaimProofRequest.setAppCallbackUrl("https://example.com/callback", true);
375
416
  ```
376
417
 
@@ -431,33 +472,51 @@ For more details about response format, check out [official documentation of Err
431
472
  const proofRequest = await ReclaimProofRequest.init(APP_ID, APP_SECRET, PROVIDER_ID, {
432
473
  useBrowserExtension: true, // Enable browser extension support (default: true)
433
474
  extensionID: "custom-extension-id", // Custom extension identifier
434
- useAppClip: true, // Enable mobile app clips (default: true)
475
+ useAppClip: false, // Enable mobile app clips (default: false)
435
476
  log: true, // Enable troubleshooting mode and more verbose logging for debugging
436
477
  });
437
478
  ```
438
479
 
439
- 9. **Custom Share Page and App Clip URLs**:
440
- You can customize the share page and app clip URLs for your app:
480
+ 9. **Custom Portal URL and App Clip URLs**:
481
+ You can customize the portal/share page and app clip URLs for your app:
441
482
 
442
483
  ```javascript
443
484
  const proofRequest = await ReclaimProofRequest.init(APP_ID, APP_SECRET, PROVIDER_ID, {
444
- customSharePageUrl: "https://your-custom-domain.com/verify", // Custom share page URL
485
+ portalUrl: "https://your-custom-domain.com/verify", // Custom URL for both portal and app modes
445
486
  customAppClipUrl: "https://appclip.apple.com/id?p=your.custom.app.clip", // Custom iOS App Clip URL
446
487
  // ... other options
447
488
  });
448
489
  ```
449
490
 
491
+ > **Defaults:**
492
+ > - Portal mode: `https://portal.reclaimprotocol.org` — remote browser verification
493
+ > - App mode: `https://share.reclaimprotocol.org` — redirects to the verifier app
494
+ >
495
+ > Setting `portalUrl` overrides both modes. The previous `customSharePageUrl` is deprecated but still supported — if both are provided, `portalUrl` takes precedence. `useAppClip` defaults to `false`.
496
+
450
497
  10. **Platform-Specific Flow Control**:
451
- The `triggerReclaimFlow()` method provides intelligent platform detection, but you can still use traditional methods for custom flows:
498
+ Both `triggerReclaimFlow()` and `getRequestUrl()` support `verificationMode`:
452
499
 
453
500
  ```javascript
454
- // Traditional approach with manual QR code handling
455
- const requestUrl = await reclaimProofRequest.getRequestUrl();
456
- // Display your own QR code implementation
501
+ // Portal flow (default) opens in new tab
502
+ const handle = await reclaimProofRequest.triggerReclaimFlow();
503
+ handle.tab; // Window reference
504
+ handle.close(); // close tab, stop polling
505
+
506
+ // Embedded portal — loads inside a DOM element
507
+ const handle = await reclaimProofRequest.triggerReclaimFlow({
508
+ target: document.getElementById('container')
509
+ });
510
+ handle.iframe; // HTMLIFrameElement reference
511
+ handle.close(); // remove iframe, stop polling
457
512
 
458
- // Or use the new streamlined approach
459
- await reclaimProofRequest.triggerReclaimFlow();
460
- // Automatically handles platform detection and optimal user experience
513
+ // Verifier app flow
514
+ const handle = await reclaimProofRequest.triggerReclaimFlow({ verificationMode: 'app' });
515
+ handle.close(); // stop polling
516
+
517
+ // getRequestUrl also supports verificationMode
518
+ const portalUrl = await reclaimProofRequest.getRequestUrl();
519
+ const appUrl = await reclaimProofRequest.getRequestUrl({ verificationMode: 'app' });
461
520
  ```
462
521
 
463
522
  11. **Exporting and Importing SDK Configuration**:
@@ -550,34 +609,153 @@ These options allow you to securely process proofs or cancellations on your serv
550
609
 
551
610
  ## Proof Verification
552
611
 
553
- The SDK provides a `verifyProof` function to manually verify proofs. This is useful when you need to validate proofs outside of the normal flow:
612
+ The SDK provides a `verifyProof` function to manually verify proofs cryptographically on your backend. This involves validating the attestor signatures and enforcing that the proof matches the expected requirements.
613
+
614
+ Here are the possible ways to use `verifyProof`, from beginner to advanced:
615
+
616
+ ### 1. Simple Verification
617
+ The easiest way is to use `request.getProviderVersion()` which returns the provider ID and exact version used in the session — pass it directly as the config:
554
618
 
555
619
  ```javascript
556
620
  import { verifyProof } from "@reclaimprotocol/js-sdk";
557
621
 
558
- // Verify a single proof
559
- const isValid = await verifyProof(proof);
560
- if (isValid) {
622
+ // Using getProviderVersion() recommended
623
+ const providerVersion = reclaimProofRequest.getProviderVersion();
624
+ const { isVerified, data, error } = await verifyProof(proof, providerVersion);
625
+ if (isVerified) {
561
626
  console.log("Proof is valid");
627
+ console.log("Context:", data[0].context);
628
+ console.log("Extracted parameters:", data[0].extractedParameters);
562
629
  } else {
563
- console.log("Proof is invalid");
630
+ console.log("Proof is invalid, reason:", error);
631
+ }
632
+ ```
633
+
634
+ Or, by manually providing the provider details:
635
+ ```javascript
636
+ const { isVerified, data } = await verifyProof(proof, {
637
+ providerId: "YOUR_PROVIDER_ID",
638
+ // The exact provider version used in the session.
639
+ providerVersion: "1.0.0",
640
+ // Optionally provide tags. For example, this can be `['ai']` when you want to allow patches from ai.
641
+ allowedTags: ["ai"]
642
+ });
643
+ ```
644
+
645
+ Or, with a known hash:
646
+ ```javascript
647
+ const { isVerified, data, error } = await verifyProof(proof, { hashes: ['0xAbC...'] });
648
+ ```
649
+
650
+ ### 2. Intermediate: Strict Hash Verification
651
+
652
+ If you want to avoid network requests, you can manually feed the expected cryptographic hashes your system allows.
653
+
654
+ ```javascript
655
+ // Verify a proof against a known, strict expected hash
656
+ const { isVerified, data } = await verifyProof(proof, {
657
+ hashes: ['0x1abc2def3456...']
658
+ });
659
+ ```
660
+
661
+ ### 3. Advanced: Multiple Proofs and Optional Matches
662
+ When building advanced use-cases, you might process multiple distinct proofs at once or deal with providers that yield a few valid hash possibilities (e.g., due to optional data fields).
663
+
664
+ ```javascript
665
+ const result = await verifyProof([proof1, proof2, sameAsProof2], {
666
+ hashes: [
667
+ // A string hash is equivalent to an object with { value: '...', required: true, multiple: true }.
668
+ '0xStrictHash123...',
669
+ {
670
+ // An array 'value' means that 1 proof can have any 1 matching hash
671
+ // from this list, typically because of optional variables in the original request.
672
+ value: ['0xOptHash1...', '0xOptHashA...'],
673
+ // 'multiple' being true (which is the default) means any proof matching this hash
674
+ // is allowed to appear multiple times in the list of proofs you are verifying.
675
+ multiple: true
676
+ },
677
+ {
678
+ value: '0xE33...',
679
+ // 'required: false' means there can be 0 proofs matching this hash.
680
+ // Such proofs may be optionally present in the list of proofs.
681
+ // (By default, 'required' is true).
682
+ required: false
683
+ }
684
+ ]
685
+ });
686
+
687
+ if (result.isVerified) {
688
+ result.data.forEach((d, i) => {
689
+ console.log(`Proof ${i + 1} context:`, d.context);
690
+ console.log(`Proof ${i + 1} params:`, d.extractedParameters);
691
+ });
564
692
  }
693
+ ```
694
+
695
+ ### 4. Danger Zone: Disabled Content Validation
696
+ If you only want to verify the attestor signature but wish to dangerously bypass the parameter/content match (Not Recommended):
697
+
698
+ ```javascript
699
+ const { isVerified } = await verifyProof(proof, {
700
+ dangerouslyDisableContentValidation: true
701
+ });
702
+ ```
703
+
704
+ ## TEE Attestation Verification
705
+
706
+ The SDK supports verifying TEE (Trusted Execution Environment) attestations included in proofs. This provides hardware-level assurance that the proof was generated inside a secure enclave (AMD SEV-SNP).
707
+
708
+ ### Enabling TEE Attestation
709
+
710
+ To request TEE attestation during proof generation, enable it during initialization:
565
711
 
566
- // Verify multiple proofs
567
- const areValid = await verifyProof([proof1, proof2, proof3]);
568
- if (areValid) {
569
- console.log("All proofs are valid");
712
+ ```javascript
713
+ const proofRequest = await ReclaimProofRequest.init(APP_ID, APP_SECRET, PROVIDER_ID, {
714
+ acceptTeeAttestation: true,
715
+ });
716
+ ```
717
+
718
+ ### Verifying TEE Attestation
719
+
720
+ Set `verifyTEE: true` in the config to require and verify TEE attestation. If TEE data is missing or invalid, verification will fail with a `TeeVerificationError`.
721
+
722
+ ```javascript
723
+ import { verifyProof, TeeVerificationError } from "@reclaimprotocol/js-sdk";
724
+
725
+ // Set verifyTEE in config to require TEE verification
726
+ const { isVerified, isTeeVerified, data, error } = await verifyProof(proof, { hashes: ['0xAbC...'], verifyTEE: true });
727
+
728
+ if (isVerified) {
729
+ console.log("Proof is fully verified with hardware attestation");
730
+ console.log("TEE verified:", isTeeVerified);
731
+ console.log("Extracted parameters:", data[0].extractedParameters);
732
+ } else if (error instanceof TeeVerificationError) {
733
+ console.log("TEE verification failed:", error.message);
570
734
  } else {
571
- console.log("One or more proofs are invalid");
735
+ console.log("Proof verification failed:", error);
572
736
  }
573
737
  ```
574
738
 
575
- The `verifyProof` function:
739
+ When `verifyTEE` is `true`, the result includes `isTeeVerified`. The overall `isVerified` will be `false` if TEE data is missing or TEE verification fails.
740
+
741
+ The TEE verification validates:
742
+ - **Nonce binding**: Ensures the attestation nonce matches the proof context
743
+ - **Application ID**: Confirms the attestation was generated for your application (optional)
744
+ - **Timestamp**: Verifies the attestation timestamp is within an acceptable range of the proof timestamp
745
+ - **SNP report**: Validates the AMD SEV-SNP hardware attestation report
746
+ - **VLEK certificate**: Verifies the certificate chain against AMD's root of trust
747
+ - **Report data**: Confirms the workload and verifier digests match the attestation
576
748
 
577
- - Accepts either a single proof or an array of proofs
578
- - Returns a boolean indicating if the proof(s) are valid
579
- - Verifies signatures, witness integrity, and claim data
580
- - Handles both standalone and blockchain-based proofs
749
+ You can also verify TEE attestation separately using the lower-level `verifyTeeAttestation` function:
750
+
751
+ ```javascript
752
+ import { verifyTeeAttestation } from "@reclaimprotocol/js-sdk";
753
+
754
+ const isTeeValid = await verifyTeeAttestation(proof, APP_ID);
755
+ if (isTeeValid) {
756
+ console.log("TEE attestation verified — proof was generated in a secure enclave");
757
+ }
758
+ ```
581
759
 
582
760
  ## Error Handling
583
761
 
@@ -628,6 +806,10 @@ try {
628
806
  - `ProofSubmissionFailedError`: Proof submission to callback failed
629
807
  - `ErrorDuringVerificationError`: An abort error during verification which was caused by the user aborting the verification process or provider's JS script raising a validation error
630
808
 
809
+ ## Example Repos
810
+
811
+ - [Reclaim Demo Website](https://github.com/reclaimprotocol/reclaim-demo-website-v3)
812
+
631
813
  ## Next Steps
632
814
 
633
815
  Explore the [Reclaim Protocol documentation](https://docs.reclaimprotocol.org/) for more advanced features and best practices for integrating the SDK into your production applications.