From c6a639473acc8f0093f2437e98f75648f30e4aa3 Mon Sep 17 00:00:00 2001 From: Karam19 Date: Thu, 6 Nov 2025 18:02:37 +0400 Subject: [PATCH] docs: update flutter in app sdk docs --- content/docs/flutter/advanced-features.mdx | 356 +++++++++++++ content/docs/flutter/api-reference.mdx | 390 +++++++++++++++ content/docs/flutter/examples.mdx | 557 +++++++++++++++++++++ content/docs/flutter/installation.mdx | 167 +++--- content/docs/flutter/meta.json | 2 +- content/docs/flutter/usage.mdx | 385 ++++++++++++-- 6 files changed, 1714 insertions(+), 143 deletions(-) create mode 100644 content/docs/flutter/advanced-features.mdx create mode 100644 content/docs/flutter/api-reference.mdx create mode 100644 content/docs/flutter/examples.mdx diff --git a/content/docs/flutter/advanced-features.mdx b/content/docs/flutter/advanced-features.mdx new file mode 100644 index 0000000..95d539f --- /dev/null +++ b/content/docs/flutter/advanced-features.mdx @@ -0,0 +1,356 @@ +--- +title: Advanced Features +description: Advanced features and customization options +--- + +Learn about advanced features and customization options available in the Reclaim Flutter SDK. + +## Theming + +The Reclaim SDK supports custom themes to match your app's branding. To enable custom theming for your application, please contact our support team. + +### Available Theme Properties + +Once custom theming is enabled for your application, the following properties can be configured: + +#### Colors + +- `primary` - Primary brand color +- `secondaryColor` - Secondary color for actions +- `surfaceColor` - Background surface color +- `green` - Success/verified state color +- `cardColor` - Card background color +- `onCardColor` - Text color on cards +- `termsNoticeColor` - Terms notice text color +- `hyperlinkColor` - Hyperlink color +- `sessionChipSurfaceColor` - Session chip background +- `sessionChipOnSurfaceColor` - Session chip text color + +#### Custom Graphics + +- `doneIconProvider` - Completion icon +- `fieldVerifiedIconProvider` - Field verified icon +- `fieldVerifyingIconProvider` - Field verifying icon +- `verificationCompleteIconProvider` - Verification complete icon +- `verifyScreenAppIconProvider` - App icon on verify screen +- `providerToAppLoader` - Loading animation between provider and app +- `loading` - General loading indicator + +#### Background + +- `background` - Background decoration +- `blurStrength` - Background blur intensity +- `blurColor` - Background blur color overlay + +#### Messages + +- `returnToAppMessage` - Message shown when returning to app + - `title` - Message title + - `subtitle` - Message subtitle +- `dataSharedMessage` - Message shown after data is shared + - `title` - Message title + - `subtitle` - Message subtitle + +#### Parameters Display + +- `parameterListStyle` - How parameters are displayed (compact or expanded) +- `dividerColor` - Color of dividers between parameters +- `isValueShown` - Whether to show parameter values + +#### Legal Links + +- `termsAndConditionsUri` - URL to your terms and conditions +- `privacyPolicyUri` - URL to your privacy policy + +#### Other + +- `cardElevation` - Elevation for card components +- `appIconGraphicOptions` - Options for app icon display + +### Contact Support + +To set up custom theming for your application, please reach out to our support team with your branding requirements. + +--- + +## Localization + +The SDK includes built-in support for multiple languages. + +### Supported Languages + +Currently supported locales: +- **English** (`en_US`) - Default +- **Spanish** (`es_ES`) + +The SDK automatically uses the device's locale if supported, falling back to English for unsupported languages. + +### Force a Specific Locale + +You can force a specific locale for the verification flow: + +```dart +await reclaim.startVerification( + request: verificationRequest, + options: ReclaimVerificationOptions( + locale: 'es_ES', // Force Spanish + ), +); +``` + +### Request Additional Language Support + +If you need support for additional languages, please contact our support team. We can work with you to add new language translations to the SDK. + +--- + +## Session Management + +### Custom Session Control + +Control whether verification can continue with custom logic: + +```dart +await reclaim.startVerification( + request: verificationRequest, + options: ReclaimVerificationOptions( + canContinueVerification: (provider, sessionInfo) async { + // Custom logic to determine if verification can proceed + final isValid = await validateSession(sessionInfo); + return isValid; + }, + ), +); +``` + +### Session Persistence + +Store and reuse session information across app restarts: + +```dart +// Generate and store session +final session = await ReclaimSessionInformation.generateNew( + providerId: providerId, + applicationId: appId, + applicationSecret: appSecret, +); +await storage.saveSession(session); + +// Reuse stored session +final storedSession = await storage.getSession(); +await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, + providerId: providerId, + sessionProvider: () => storedSession, + ), +); +``` + +--- + +## WebView Configuration + +### Clear WebView Storage + +Control whether to clear webview storage before verification: + +```dart +await reclaim.startVerification( + request: verificationRequest, + options: ReclaimVerificationOptions( + canClearWebStorage: false, // Keep cookies/storage + ), +); +``` + +**Use Cases:** +- Preserve login sessions across verifications +- Reduce re-authentication needs +- Speed up subsequent verifications + +**Default:** `true` (storage is cleared before each verification) + +--- + +## UI Customization + +### Auto-Submit + +Automatically submit when verification data is ready: + +```dart +await reclaim.startVerification( + request: verificationRequest, + options: ReclaimVerificationOptions( + canAutoSubmit: true, + ), +); +``` + +This skips the review step and submits immediately when data is collected. + +**Default:** `false` + +### Hide Close Button + +Remove the close button from the verification UI: + +```dart +await reclaim.startVerification( + request: verificationRequest, + options: ReclaimVerificationOptions( + isCloseButtonVisible: false, + ), +); +``` + +**Useful For:** +- Mandatory verification flows +- Preventing accidental dismissal +- Guided onboarding processes + +**Default:** `true` + +--- + +## Custom Parameters + +Some providers require specific data to complete verification. These custom parameters are determined by the provider's requirements. + +### Providing Custom Parameters + +Pass the required parameters when starting verification: + +```dart +await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, + providerId: providerId, + sessionProvider: sessionProvider, + parameters: { + 'username': 'john_doe', + 'account_id': '12345', + 'region': 'US', + }, + ), +); +``` + +Check the specific provider's documentation in the [Provider Explorer](https://dev.reclaimprotocol.org/explore) to see what parameters it requires. + +--- +## Context Strings + +Add additional context to verifications that will be included in the proof: + +```dart +await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, + providerId: providerId, + sessionProvider: sessionProvider, + contextString: json.encode({ + 'user_id': userId, + 'action': 'account_verification', + 'timestamp': DateTime.now().toIso8601String(), + }), + ), +); +``` + +**Use Cases:** +- Tracking verification purposes +- Binding verifications to specific actions +- Adding metadata to proofs +- Audit trails + +--- + +## Security Best Practices + +### 1. Never Hardcode Secrets + +Always use environment variables or secure storage: + +```dart +// ✅ Good +const appSecret = String.fromEnvironment('APP_SECRET'); + +// ❌ Bad +const appSecret = 'my-secret-123'; +``` + +### 2. Handle Exceptions Properly + +Don't expose sensitive error details to users: + +```dart +try { + await reclaim.startVerification(...); +} catch (e) { + // Log detailed error internally + logger.error('Verification failed', e); + + // Show generic message to user + showDialog('Verification failed. Please try again.'); +} +``` + +### 3. Secure Storage + +Store sensitive data securely: + +```dart +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +final secureStorage = FlutterSecureStorage(); + +// Store session securely +await secureStorage.write( + key: 'reclaim_session', + value: json.encode(session.toJson()), +); +``` + +--- + +## Platform-Specific Considerations + +### Android + +#### Cronet for Devices Without Play Services + +On devices without Google Play Services, add embedded Cronet: + +```gradle +dependencies { + implementation("org.chromium.net:cronet-embedded:119.6045.31") +} +``` + +### iOS + +Ensure minimum iOS version is set: + +```ruby +platform :ios, '13.0' +``` + +--- + +## Getting Help + +For advanced customization, additional language support, or custom theming: + +- **Telegram Community**: [t.me/protocolreclaim](https://t.me/protocolreclaim) +- **Twitter**: [@reclaimprotocol](https://twitter.com/reclaimprotocol) +- **Support**: Contact our support team for custom requirements + +--- + +## Next Steps + +- Check out [Examples](/docs/flutter/examples) for practical implementations +- Review the [API Reference](/docs/flutter/api-reference) for detailed class documentation +- Read the [Usage Guide](/docs/flutter/usage) for basic implementation patterns diff --git a/content/docs/flutter/api-reference.mdx b/content/docs/flutter/api-reference.mdx new file mode 100644 index 0000000..660ccd9 --- /dev/null +++ b/content/docs/flutter/api-reference.mdx @@ -0,0 +1,390 @@ +--- +title: API Reference +description: Complete API reference for the Reclaim Flutter SDK +--- + +Complete reference documentation for all public classes, methods, and types in the Reclaim Flutter SDK. + +## ReclaimVerification + +Main class for managing verification flows. + +### Constructor + +**`ReclaimVerification.of(BuildContext context)`** + +Creates an instance from a BuildContext. + +- **Parameters:** + - `context` - The BuildContext from your widget +- **Returns:** ReclaimVerification instance + +### Methods + +**`Future startVerification({required ReclaimVerificationRequest request, ReclaimVerificationOptions options})`** + +Starts a verification flow. + +- **Parameters:** + - `request` - Verification request configuration + - `options` - Optional verification options (defaults to `ReclaimVerificationOptions()`) +- **Returns:** Future that resolves to ReclaimVerificationResult +- **Throws:** Various ReclaimException subclasses + +**`Future cancelPendingVerifications()`** + +Cancels any pending verifications. + +- **Returns:** true if verifications were cancelled + +--- + +## ReclaimVerificationRequest + +Configuration for a verification request. + +### Constructor + +**`ReclaimVerificationRequest({required String applicationId, required String providerId, required SessionProvider sessionProvider, String? contextString, Map parameters})`** + +- **Parameters:** + - `applicationId` (required) - Your application ID + - `providerId` (required) - Provider ID to verify + - `sessionProvider` (required) - Function returning session information + - `contextString` (optional) - Additional context + - `parameters` (optional) - Custom parameters required by the provider (defaults to empty map) + +### Properties + +- `String applicationId` - Application identifier +- `String providerId` - Provider identifier +- `SessionProvider sessionProvider` - Session provider function +- `String? contextString` - Context string +- `Map parameters` - Custom parameters required by the provider + +--- + +## ReclaimVerificationOptions + +Optional configuration for verification behavior. + +### Constructor + +**`ReclaimVerificationOptions({bool canAutoSubmit, bool isCloseButtonVisible, bool canClearWebStorage, ReclaimAttestorAuthenticationRequestCallback? attestorAuthenticationRequest, CanContinueVerificationCallback? canContinueVerification, AttestorZkOperator? attestorZkOperator, String? locale})`** + +All parameters are optional with the following defaults: +- `canAutoSubmit` - false +- `isCloseButtonVisible` - true +- `canClearWebStorage` - true +- `attestorAuthenticationRequest` - null +- `canContinueVerification` - null +- `attestorZkOperator` - null +- `locale` - null + +### Properties + +- `bool canAutoSubmit` - Auto-submit when ready +- `bool isCloseButtonVisible` - Show close button +- `bool canClearWebStorage` - Clear storage before verification +- `ReclaimAttestorAuthenticationRequestCallback? attestorAuthenticationRequest` - Custom attestor auth +- `CanContinueVerificationCallback? canContinueVerification` - Verification control callback +- `AttestorZkOperator? attestorZkOperator` - Custom ZK operator +- `String? locale` - Force specific locale + +--- + +## ReclaimSessionInformation + +Session authentication information. + +### Constructor + +**`ReclaimSessionInformation({required String sessionId, required String signature, required String timestamp, required ProviderVersionExact version})`** + +- **Parameters:** + - `sessionId` (required) - Session identifier + - `signature` (required) - Session signature + - `timestamp` (required) - Session timestamp + - `version` (required) - Provider version + +### Static Methods + +**`static Future generateNew({required String applicationId, required String applicationSecret, required String providerId, String providerVersion})`** + +Generates a new session. + +- **Parameters:** + - `applicationId` (required) - Application ID + - `applicationSecret` (required) - Application secret + - `providerId` (required) - Provider ID + - `providerVersion` (optional) - Version constraint (defaults to empty string) +- **Returns:** Future resolving to new ReclaimSessionInformation + +### Properties + +- `String sessionId` - Session ID +- `String signature` - Cryptographic signature +- `String timestamp` - Timestamp string +- `ProviderVersionExact version` - Provider version info +- `bool isValid` - Whether signature and timestamp are valid + +--- + +## ReclaimVerificationResult + +Result of a successful verification. + +### Properties + +- `HttpProvider provider` - Provider information +- `String exactProviderVersion` - Exact provider version used +- `List proofs` - List of generated proofs + +### Methods + +**`Map toJson()`** + +Converts result to JSON map. + +--- + +## CreateClaimOutput + +A single proof from verification. + +### Properties + +- `String identifier` - Unique proof identifier +- `ProviderClaimData claimData` - Claim metadata +- `List signatures` - Cryptographic signatures +- `List witnesses` - Witness data list +- `Object? publicData` - Public data from verification +- `int? taskId` - Optional task ID + +### Methods + +**`Map toJson()`** + +Converts to JSON map. + +**`static CreateClaimOutput fromJson(Map json)`** + +Creates instance from JSON. + +**`CreateClaimOutput copyWith({int? taskId, Object? publicData})`** + +Creates a copy with updated fields. + +--- + +## ProviderClaimData + +Metadata about a claim. + +### Properties + +- `String provider` - Provider name +- `String parameters` - Serialized parameters +- `String owner` - Claim owner +- `int timestampS` - Unix timestamp (seconds) +- `String context` - Context string +- `String identifier` - Claim identifier +- `int epoch` - Epoch number + +### Methods + +**`Map toJson()`** + +Converts to JSON. + +**`static ProviderClaimData fromJson(Map json)`** + +Creates from JSON. + +--- + +## WitnessData + +Witness information. + +### Properties + +- `String id` - Witness ID +- `String url` - Witness URL + +### Methods + +**`Map toJson()`** + +Converts to JSON. + +**`static WitnessData fromJson(Map json)`** + +Creates from JSON. + +--- + +## Exceptions + +All exceptions extend `ReclaimException`. + +### ReclaimException + +Base exception class. + +**Properties:** +- `String? message` - Error message +- `String exceptionName` - Exception type name + +**Methods:** +- `Map toJson()` - Convert to JSON + +### Session Exceptions + +**`ReclaimExpiredSessionException([String? message])`** +- Session expired or invalid + +**`ReclaimInitSessionException([String? message])`** +- Session initialization failed + +### Verification Exceptions + +**`ReclaimVerificationCancelledException([String? message])`** +- Verification cancelled + +**`ReclaimVerificationDismissedException([String? message])`** +- User dismissed verification + +**`ReclaimVerificationSkippedException([String? message])`** +- Verification skipped + +**`ReclaimVerificationPlatformNotSupportedException([String? message])`** +- Platform not supported (requires 64-bit) + +**`ReclaimVerificationOutdatedSDKException([String? message])`** +- SDK version is outdated + +**`InvalidRequestReclaimException([String? message])`** +- Invalid request parameters + +### Provider Exceptions + +Base: **`ReclaimVerificationProviderException([String? message])`** + +**`ReclaimVerificationProviderNotFoundException()`** +- Provider not found + +**`ReclaimVerificationProviderScriptException(String message, [Map? providerError])`** +- Provider script error +- Additional property: `Map? providerError` + +**`ReclaimVerificationNoActivityDetectedException(String message)`** +- No activity detected + +**`ReclaimVerificationRequirementException()`** +- Verification requirements not met + +**`ReclaimVerificationProviderLoadException([String? message])`** +- Provider loading failed + +**`ReclaimAttestorException(String message)`** +- Attestor error + +--- + +## Type Aliases + +**`typedef SessionProvider = FutureOr Function()`** + +Function that provides session information (sync or async). + +**`typedef ReclaimAttestorAuthenticationRequestCallback = FutureOr Function(HttpProvider provider)`** + +Callback for custom attestor authentication. + +**`typedef CanContinueVerificationCallback = Future Function(HttpProvider provider, ReclaimSessionInformation sessionInformation)`** + +Callback to control verification flow continuation. + +--- + +## Theme Classes + +### ReclaimTheme + +Theme customization for verification UI. + +See [Advanced Features](/docs/flutter/advanced-features) for detailed theming documentation. + +### ReclaimThemeProvider + +Widget that provides theme to verification flow. + +**Constructor:** +```dart +ReclaimThemeProvider({ + required String? applicationId, + required Widget Function(BuildContext) builder, +}) +``` + +--- + +## Version Classes + +### ProviderVersionExact + +Represents an exact provider version. + +**Constructor:** +```dart +ProviderVersionExact(String version, {String versionExpression}) +``` + +**Parameters:** +- `version` - Exact version string +- `versionExpression` (optional) - Version constraint expression + +--- + +## Utility Classes + +### AttestorZkOperator + +Interface for ZK proof computation. + +**Methods:** +- `Future isPlatformSupported()` - Check if platform is supported +- `Future computeProof(...)` - Compute ZK proof + +### AttestorZkOperatorWithCallback + +Implementation with custom callbacks. + +**Static Constructor:** +```dart +static AttestorZkOperatorWithCallback.withReclaimZKOperator({ + required OnComputeProof onComputeProof, + required Future Function() isPlatformSupported, +}) +``` + +--- + +## Constants + +The SDK uses default values for several configurations: +- Default auto-submit: `false` +- Default close button visibility: `true` +- Default clear web storage: `true` +- Empty provider version constraint: `''` + +--- + +## Import Path + +```dart +import 'package:reclaim_inapp_sdk/reclaim_inapp_sdk.dart'; +``` + +This exports all public API classes and types. diff --git a/content/docs/flutter/examples.mdx b/content/docs/flutter/examples.mdx new file mode 100644 index 0000000..51e4831 --- /dev/null +++ b/content/docs/flutter/examples.mdx @@ -0,0 +1,557 @@ +--- +title: Examples +description: Practical examples for common use cases +--- + +Explore practical examples for implementing Reclaim Protocol verification in your Flutter app. + +## Basic Verification + +Simple verification with minimal configuration. + +```dart +import 'package:flutter/material.dart'; +import 'package:reclaim_inapp_sdk/reclaim_inapp_sdk.dart'; + +class BasicVerificationExample extends StatelessWidget { + const BasicVerificationExample({super.key}); + + Future startVerification(BuildContext context) async { + final messenger = ScaffoldMessenger.of(context); + + try { + final reclaim = ReclaimVerification.of(context); + + final result = await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, + providerId: providerId, + sessionProvider: () => ReclaimSessionInformation.generateNew( + providerId: providerId, + applicationId: appId, + applicationSecret: appSecret, + ), + ), + ); + + // Handle success + print('Verification completed with ${result.proofs.length} proofs'); + + } catch (e) { + messenger.showSnackBar( + SnackBar(content: Text('Verification failed: $e')), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Basic Verification')), + body: Center( + child: ElevatedButton( + onPressed: () => startVerification(context), + child: const Text('Start Verification'), + ), + ), + ); + } +} +``` + +--- + +## Error Handling + +Comprehensive error handling for all exception types. + +```dart +class VerificationWithErrorHandling extends StatelessWidget { + const VerificationWithErrorHandling({super.key}); + + Future startVerification(BuildContext context) async { + final messenger = ScaffoldMessenger.of(context); + + try { + final reclaim = ReclaimVerification.of(context); + + final result = await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, + providerId: providerId, + sessionProvider: () => ReclaimSessionInformation.generateNew( + providerId: providerId, + applicationId: appId, + applicationSecret: appSecret, + ), + ), + ); + + messenger.showSnackBar( + const SnackBar( + content: Text('✓ Verification successful'), + backgroundColor: Colors.green, + ), + ); + + } on ReclaimExpiredSessionException { + messenger.showSnackBar( + const SnackBar( + content: Text('Session expired. Please try again.'), + backgroundColor: Colors.orange, + ), + ); + + } on ReclaimVerificationDismissedException { + // User cancelled - no error message needed + print('User cancelled verification'); + + } on ReclaimVerificationPlatformNotSupportedException { + messenger.showSnackBar( + const SnackBar( + content: Text('Your device is not supported.'), + backgroundColor: Colors.red, + ), + ); + + } on InvalidRequestReclaimException catch (e) { + messenger.showSnackBar( + SnackBar( + content: Text('Invalid request: ${e.message}'), + backgroundColor: Colors.red, + ), + ); + + } on ReclaimVerificationProviderException catch (e) { + messenger.showSnackBar( + SnackBar( + content: Text('Provider error: ${e.message}'), + backgroundColor: Colors.red, + ), + ); + + } catch (e) { + messenger.showSnackBar( + SnackBar( + content: Text('Unexpected error: $e'), + backgroundColor: Colors.red, + ), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Error Handling')), + body: Center( + child: ElevatedButton( + onPressed: () => startVerification(context), + child: const Text('Start Verification'), + ), + ), + ); + } +} +``` + +--- + +## Auto-Submit Verification + +Automatically submit verification without user review. + +```dart +class AutoSubmitVerification extends StatelessWidget { + const AutoSubmitVerification({super.key}); + + Future startVerification(BuildContext context) async { + try { + final reclaim = ReclaimVerification.of(context); + + final result = await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, + providerId: providerId, + sessionProvider: () => ReclaimSessionInformation.generateNew( + providerId: providerId, + applicationId: appId, + applicationSecret: appSecret, + ), + ), + options: ReclaimVerificationOptions( + canAutoSubmit: true, // Enable auto-submit + ), + ); + + print('Auto-submitted with ${result.proofs.length} proofs'); + + } catch (e) { + print('Verification failed: $e'); + } + } + + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: () => startVerification(context), + child: const Text('Start Auto-Submit Verification'), + ); + } +} +``` + +--- + +## Custom Parameters + +Provide custom parameters required by certain providers. + +```dart +class CustomParametersExample extends StatefulWidget { + const CustomParametersExample({super.key}); + + @override + State createState() => _CustomParametersExampleState(); +} + +class _CustomParametersExampleState extends State { + final _usernameController = TextEditingController(); + + @override + void dispose() { + _usernameController.dispose(); + super.dispose(); + } + + Future _startVerification() async { + if (_usernameController.text.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Please enter a username')), + ); + return; + } + + try { + final reclaim = ReclaimVerification.of(context); + + // Some providers require specific parameters + // Check the provider documentation to see what's required + final result = await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, + providerId: providerId, + sessionProvider: () => ReclaimSessionInformation.generateNew( + providerId: providerId, + applicationId: appId, + applicationSecret: appSecret, + ), + parameters: { + 'username': _usernameController.text, + }, + ), + ); + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Verification complete!')), + ); + + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Error: $e')), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Custom Parameters')), + body: Padding( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'This provider requires a username parameter', + style: TextStyle(color: Colors.grey[600]), + ), + SizedBox(height: 16), + TextField( + controller: _usernameController, + decoration: InputDecoration( + labelText: 'Username', + border: OutlineInputBorder(), + ), + ), + SizedBox(height: 16), + ElevatedButton( + onPressed: _startVerification, + child: const Text('Verify with Username'), + ), + ], + ), + ), + ); + } +} +``` + +--- + +## Context String Usage + +Add context to bind verification to specific actions. + +```dart +class ContextStringExample extends StatelessWidget { + final String userId; + final String orderId; + + const ContextStringExample({ + super.key, + required this.userId, + required this.orderId, + }); + + Future startVerification(BuildContext context) async { + try { + final reclaim = ReclaimVerification.of(context); + + // Create context with action details + final contextData = { + 'user_id': userId, + 'order_id': orderId, + 'action': 'order_verification', + 'timestamp': DateTime.now().toIso8601String(), + }; + + final result = await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, + providerId: providerId, + sessionProvider: () => ReclaimSessionInformation.generateNew( + providerId: providerId, + applicationId: appId, + applicationSecret: appSecret, + ), + contextString: json.encode(contextData), + ), + ); + + // The context is now embedded in the proof + print('Verification complete with context: $contextData'); + + } catch (e) { + print('Verification failed: $e'); + } + } + + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: () => startVerification(context), + child: const Text('Verify Order'), + ); + } +} +``` + +--- + +## Processing Proofs + +Extract and use data from verification proofs. + +```dart +class ProofProcessingExample extends StatelessWidget { + const ProofProcessingExample({super.key}); + + void _processProofs(ReclaimVerificationResult result) { + print('Provider: ${result.provider.name}'); + print('Version: ${result.exactProviderVersion}'); + print('Total proofs: ${result.proofs.length}'); + + for (var i = 0; i < result.proofs.length; i++) { + final proof = result.proofs[i]; + + print('\n--- Proof ${i + 1} ---'); + print('Identifier: ${proof.identifier}'); + print('Owner: ${proof.claimData.owner}'); + print('Timestamp: ${DateTime.fromMillisecondsSinceEpoch(proof.claimData.timestampS * 1000)}'); + print('Context: ${proof.claimData.context}'); + print('Signatures: ${proof.signatures.length}'); + print('Witnesses: ${proof.witnesses.length}'); + + // Extract public data + if (proof.publicData != null) { + print('Public Data: ${json.encode(proof.publicData)}'); + } + + // Witness information + for (var witness in proof.witnesses) { + print('Witness ${witness.id}: ${witness.url}'); + } + } + } + + Future startVerification(BuildContext context) async { + try { + final reclaim = ReclaimVerification.of(context); + + final result = await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, + providerId: providerId, + sessionProvider: () => ReclaimSessionInformation.generateNew( + providerId: providerId, + applicationId: appId, + applicationSecret: appSecret, + ), + ), + ); + + // Process the proofs + _processProofs(result); + + // Send to backend for validation + await _sendProofsToBackend(result.proofs); + + } catch (e) { + print('Verification failed: $e'); + } + } + + Future _sendProofsToBackend(List proofs) async { + // Example: Send proofs to your backend + final proofsJson = proofs.map((p) => p.toJson()).toList(); + + // Make API call to your backend + // await http.post( + // Uri.parse('https://your-api.com/verify-proofs'), + // body: json.encode({'proofs': proofsJson}), + // ); + + print('Proofs sent to backend for validation'); + } + + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: () => startVerification(context), + child: const Text('Verify and Process Proofs'), + ); + } +} +``` + +--- + +## Multi-Provider Verification + +Verify multiple providers sequentially. + +```dart +class MultiProviderExample extends StatefulWidget { + const MultiProviderExample({super.key}); + + @override + State createState() => _MultiProviderExampleState(); +} + +class _MultiProviderExampleState extends State { + final List _providerIds = [ + 'provider-id-1', + 'provider-id-2', + 'provider-id-3', + ]; + + final Map _results = {}; + int _currentProviderIndex = 0; + bool _isVerifying = false; + + Future _startMultiVerification() async { + setState(() { + _isVerifying = true; + _currentProviderIndex = 0; + _results.clear(); + }); + + final reclaim = ReclaimVerification.of(context); + + for (int i = 0; i < _providerIds.length; i++) { + setState(() => _currentProviderIndex = i); + + try { + final result = await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, + providerId: _providerIds[i], + sessionProvider: () => ReclaimSessionInformation.generateNew( + providerId: _providerIds[i], + applicationId: appId, + applicationSecret: appSecret, + ), + ), + ); + + _results[_providerIds[i]] = result; + + } on ReclaimVerificationDismissedException { + // User cancelled + break; + } catch (e) { + print('Provider ${_providerIds[i]} failed: $e'); + // Continue with next provider + } + } + + setState(() => _isVerifying = false); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Completed ${_results.length}/${_providerIds.length} verifications'), + ), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Multi-Provider Verification')), + body: Center( + child: _isVerifying + ? Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircularProgressIndicator(), + SizedBox(height: 16), + Text('Verifying provider ${_currentProviderIndex + 1}/${_providerIds.length}'), + ], + ) + : Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + onPressed: _startMultiVerification, + child: const Text('Start Multi-Verification'), + ), + if (_results.isNotEmpty) ...[ + SizedBox(height: 24), + Text('Completed: ${_results.length}/${_providerIds.length}'), + ], + ], + ), + ), + ); + } +} +``` + +--- + +## Next Steps + +- Review the [Usage Guide](/docs/flutter/usage) for basic implementation +- Check the [API Reference](/docs/flutter/api-reference) for detailed documentation +- Explore [Advanced Features](/docs/flutter/advanced-features) for customization options diff --git a/content/docs/flutter/installation.mdx b/content/docs/flutter/installation.mdx index 72cf886..355ba5d 100644 --- a/content/docs/flutter/installation.mdx +++ b/content/docs/flutter/installation.mdx @@ -1,141 +1,128 @@ --- title: Installation -description: Flutter SDK for Reclaim Protocol +description: Install and set up the Reclaim Flutter SDK --- - -The Reclaim Protocol SDK for Flutter (android & iOS) applications is ready and available upon request. Contact our team to discuss implementation details. - - -A Flutter SDK for integrating Reclaim's verification system directly into your Flutter applications. This SDK allows you to verify user credentials and generate proofs in-app. +The Reclaim Flutter SDK provides a seamless way to integrate Reclaim Protocol's verification system directly into your Flutter applications for both Android and iOS platforms. ## Features -- In-app verification flow -- Customizable verification options -- ZK Proof generation -- Compatible when using Flutter "Add to App modules" in your native applications +- In-app verification flow with native UI +- Zero-knowledge proof generation +- Customizable themes and localization +- AI-assisted verification flows +- Compatible with "Add to App" Flutter modules +- Cross-platform support (Android 5.0+ and iOS 13.0+) ## Prerequisites -- An Android application source code (Support for Android 5.0 or later). -- An Android device or emulator running Android 5.0 or later. -- A Reclaim account where you've created an app and have the app id, app secret. -- A provider id that you've added to your app in Reclaim Devtools. +Before you begin, ensure you have: + +1. **Flutter Environment**: Flutter SDK 3.35.0 or later with Dart 3.9.0 or later +2. **Reclaim Developer Account**: Login to [Reclaim Developer Tool](https://dev.reclaimprotocol.org/) +3. **Application Credentials**: + - Create an application at [Reclaim Developer Tool](https://dev.reclaimprotocol.org/new-application) + - Obtain your Application ID and Application Secret +4. **Provider ID**: Choose a data provider from [Provider Explorer](https://dev.reclaimprotocol.org/explore) ## Get an API Key -Setup your project using the [Get API Key guide](/api-key). + +Set up your project credentials using the [Get API Key guide](/api-key). ## Installation -Add the following to your `pubspec.yaml`: +Add the Reclaim SDK to your Flutter project: -```yaml -dependencies: - reclaim_inapp_flutter_sdk: ^latest_version +### Using Flutter CLI + +```bash +flutter pub add reclaim_inapp_sdk ``` +### Manual Installation -## Usage +Add the following to your `pubspec.yaml`: -### Basic Setup +```yaml +dependencies: + reclaim_inapp_sdk: ^latest_version +``` -1. Import the SDK in your Dart file: +Then run: -```dart -import 'package:reclaim_inapp_flutter_sdk/reclaim_inapp_flutter_sdk.dart'; +```bash +flutter pub get ``` -2. Initialize the SDK with your app credentials: +## Platform-Specific Configuration -Following is an exmaple. +### Android Configuration -```dart -const String appId = String.fromEnvironment('APP_ID'); -const String appSecret = String.fromEnvironment('APP_SECRET'); -const String providerId = String.fromEnvironment('PROVIDER_ID'); -``` +#### Minimum Requirements -### Starting Verification +Update your `android/app/build.gradle`: -```dart -final sdk = ReclaimInAppSdk.of(context); -final proofs = await sdk.startVerification( - ReclaimVerificationRequest( - appId: appId, - providerId: providerId, - secret: appSecret, - sessionInformation: ReclaimSessionInformation.empty(), - contextString: '', - parameters: {}, - claimCreationType: ClaimCreationType.standalone, - ), -); +```gradle +android { + defaultConfig { + minSdkVersion 21 // Minimum Android 5.0 + targetSdkVersion 34 + } +} ``` -### Configuration Options +#### Cronet for Devices Without Play Services -The `ReclaimVerificationRequest` supports the following options: +If you need to support Android devices without Google Play Services, add the embedded Cronet library: -- `appId`: Your Reclaim application ID -- `providerId`: The ID of the provider you want to verify against -- `secret`: Your application secret (optional if using session information) -- `sessionInformation`: Session information for authentication -- `contextString`: Additional context for the verification -- `parameters`: Custom parameters for the verification -- `claimCreationType`: Type of claim creation (standalone or meChain) -- `autoSubmit`: Whether to auto-submit the verification -- `hideCloseButton`: Whether to hide the close button -- `webhookUrl`: URL for webhook notifications -- `verificationOptions`: Additional verification options +```gradle +dependencies { + // Use embedded cronet for devices without play services + implementation("org.chromium.net:cronet-embedded:119.6045.31") +} +``` -### Error Handling +### iOS Configuration -The SDK throws specific exceptions that you can handle: +Update your `ios/Podfile`: -```dart -try { - final proofs = await sdk.startVerification(request); -} on ReclaimExpiredSessionException { - // Handle expired session -} on ReclaimVerificationManualReviewException { - // Handle manual review case -} catch (error) { - // Handle other errors if required -} +```ruby +platform :ios, '13.0' # Minimum iOS 13.0 ``` -### Pre-warming +## Environment Variables -For better performance, you can pre-warm the SDK: +For security best practices, store your credentials using environment variables: -```dart -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - ReclaimInAppSdk.preWarm(); - runApp(MyApp()); -} +Create a `.env` file in your project root: + +```env +APP_ID=your_application_id_here +APP_SECRET=your_application_secret_here +PROVIDER_ID=your_provider_id_here ``` -## Example +Run your app with the environment file: -Check out the [example](example/lib/main.dart) for a complete implementation. +```bash +flutter run --dart-define-from-file=./.env +``` -## Environment Variables +Access the values in your Dart code: -The SDK requires the following environment variables: +```dart +const String appId = String.fromEnvironment('APP_ID'); +const String appSecret = String.fromEnvironment('APP_SECRET'); +const String providerId = String.fromEnvironment('PROVIDER_ID'); +``` -- `APP_ID`: Your Reclaim application ID -- `APP_SECRET`: Your application secret -- `PROVIDER_ID`: The ID of the provider to verify against +## Next Steps -You can provide these values using: +After installation, continue to the [Usage](/docs/flutter/usage) guide to learn how to implement verification in your app. -- Dart Define Env file: `--dart-define-from-file=./.env` -- Hardcoded values (not recommended for production) -### Stay Updated +## Stay Updated - Join our [Telegram community](https://t.me/protocolreclaim) - Follow [@reclaimprotocol](https://twitter.com/reclaimprotocol) on Twitter -- Watch our [GitHub repository](https://github.com/reclaimprotocol) +- Watch our [GitHub repository](https://github.com/reclaimprotocol) \ No newline at end of file diff --git a/content/docs/flutter/meta.json b/content/docs/flutter/meta.json index 9f8a1cf..78961c4 100644 --- a/content/docs/flutter/meta.json +++ b/content/docs/flutter/meta.json @@ -1,4 +1,4 @@ { "title": "Flutter SDK", - "pages": ["installation", "usage"] + "pages": ["installation", "usage", "api-reference", "advanced-features", "examples"] } \ No newline at end of file diff --git a/content/docs/flutter/usage.mdx b/content/docs/flutter/usage.mdx index 8fd95ca..552466d 100644 --- a/content/docs/flutter/usage.mdx +++ b/content/docs/flutter/usage.mdx @@ -1,16 +1,23 @@ --- title: Usage -description: Flutter SDK for Reclaim Protocol +description: Learn how to use the Reclaim Flutter SDK --- -1. Import the SDK in your Dart file: + +This guide will walk you through implementing Reclaim Protocol verification in your Flutter application. + +## Quick Start + +### 1. Import the SDK + +Import the Reclaim SDK in your Dart file: ```dart -import 'package:reclaim_inapp_flutter_sdk/reclaim_inapp_flutter_sdk.dart'; +import 'package:reclaim_inapp_sdk/reclaim_inapp_sdk.dart'; ``` -2. Initialize the SDK with your app credentials: +### 2. Set Up Credentials -Following is an exmaple. +Use environment variables for your credentials: ```dart const String appId = String.fromEnvironment('APP_ID'); @@ -18,79 +25,353 @@ const String appSecret = String.fromEnvironment('APP_SECRET'); const String providerId = String.fromEnvironment('PROVIDER_ID'); ``` -### Starting Verification +### 3. Initialize ReclaimVerification + +Create a `ReclaimVerification` instance from your BuildContext: ```dart -final sdk = ReclaimInAppSdk.of(context); -final proofs = await sdk.startVerification( - ReclaimVerificationRequest( - appId: appId, +final reclaim = ReclaimVerification.of(context); +``` + +### 4. Start Verification + +Call `startVerification()` to begin the verification flow: + +```dart +final result = await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, providerId: providerId, - secret: appSecret, - sessionInformation: ReclaimSessionInformation.empty(), - contextString: '', - parameters: {}, - claimCreationType: ClaimCreationType.standalone, + sessionProvider: () => ReclaimSessionInformation.generateNew( + providerId: providerId, + applicationId: appId, + applicationSecret: appSecret, + ), ), ); + +// Access the proofs +final proofs = result.proofs; +print('Received ${proofs.length} proofs'); +``` + +## Complete Example + +Here's a complete example of a verification flow: + +```dart +import 'package:flutter/material.dart'; +import 'package:reclaim_inapp_sdk/reclaim_inapp_sdk.dart'; + +class VerificationScreen extends StatelessWidget { + const VerificationScreen({super.key}); + + Future startVerification(BuildContext context) async { + final messenger = ScaffoldMessenger.of(context); + + try { + final reclaim = ReclaimVerification.of(context); + + final result = await reclaim.startVerification( + request: ReclaimVerificationRequest( + applicationId: appId, + providerId: providerId, + sessionProvider: () => ReclaimSessionInformation.generateNew( + providerId: providerId, + applicationId: appId, + applicationSecret: appSecret, + ), + ), + ); + + // Success - handle the proofs + messenger.showSnackBar( + SnackBar(content: Text('Verification successful! Got ${result.proofs.length} proofs')), + ); + + } on ReclaimExpiredSessionException catch (e) { + messenger.showSnackBar( + SnackBar(content: Text('Session expired: ${e.message}')), + ); + } on ReclaimVerificationDismissedException { + messenger.showSnackBar( + const SnackBar(content: Text('Verification cancelled by user')), + ); + } catch (e) { + messenger.showSnackBar( + SnackBar(content: Text('Verification failed: $e')), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Reclaim Verification')), + body: Center( + child: ElevatedButton( + onPressed: () => startVerification(context), + child: const Text('Start Verification'), + ), + ), + ); + } +} +``` + +## Understanding the Response + +The `startVerification()` method returns a `ReclaimVerificationResult` containing: + +```dart +class ReclaimVerificationResult { + final HttpProvider provider; // Provider information + final String exactProviderVersion; // Provider version used + final List proofs; // Generated proofs +} +``` + +### Proof Structure + +Each proof (`CreateClaimOutput`) contains: + +```dart +class CreateClaimOutput { + final String identifier; // Unique identifier + final ProviderClaimData claimData; // Claim data + final List signatures; // Cryptographic signatures + final List witnesses; // Witness information + final Object? publicData; // Public data from verification +} +``` + +### Accessing Proof Data + +```dart +final result = await reclaim.startVerification(...); + +for (final proof in result.proofs) { + print('Proof ID: ${proof.identifier}'); + print('Timestamp: ${proof.claimData.timestampS}'); + print('Context: ${proof.claimData.context}'); + print('Public Data: ${proof.publicData}'); + print('Signatures: ${proof.signatures.length}'); +} ``` -### Configuration Options +## Configuration Options + +### ReclaimVerificationRequest -The `ReclaimVerificationRequest` supports the following options: +Configure the verification request: + +```dart +ReclaimVerificationRequest( + applicationId: 'your-app-id', + providerId: 'your-provider-id', + sessionProvider: () => ReclaimSessionInformation.generateNew(...), + contextString: 'optional-context', // Additional context + parameters: {'key': 'value'}, // Custom parameters +) +``` -- `appId`: Your Reclaim application ID -- `providerId`: The ID of the provider you want to verify against -- `secret`: Your application secret (optional if using session information) -- `sessionInformation`: Session information for authentication -- `contextString`: Additional context for the verification -- `parameters`: Custom parameters for the verification -- `claimCreationType`: Type of claim creation (standalone or meChain) -- `autoSubmit`: Whether to auto-submit the verification -- `hideCloseButton`: Whether to hide the close button -- `webhookUrl`: URL for webhook notifications -- `verificationOptions`: Additional verification options +**Parameters:** +- `applicationId` (required): Your Reclaim application ID +- `providerId` (required): The provider ID to verify against +- `sessionProvider` (required): Function that returns session information +- `contextString` (optional): Additional context for the verification +- `parameters` (optional): Map of key-value pairs to provide custom data to the provider -### Error Handling +### ReclaimVerificationOptions -The SDK throws specific exceptions that you can handle: +Customize the verification behavior: + +```dart +await reclaim.startVerification( + request: verificationRequest, + options: ReclaimVerificationOptions( + canAutoSubmit: true, // Auto-submit when data is ready + isCloseButtonVisible: true, // Show/hide close button + canClearWebStorage: true, // Clear webview storage before verification + locale: 'en_US', // Force specific locale + ), +); +``` + +**Available Options:** +- `canAutoSubmit`: Whether to automatically submit the verification when ready (default: `false`) +- `isCloseButtonVisible`: Show or hide the close button in the verification UI (default: `true`) +- `canClearWebStorage`: Clear webview storage before starting (default: `true`) +- `attestorZkOperator`: Custom ZK operator for proof generation +- `locale`: Force a specific locale (e.g., `'en_US'`, `'es_ES'`) + +## Error Handling + +The SDK throws specific exceptions that you should handle: + +### Common Exceptions ```dart try { - final proofs = await sdk.startVerification(request); + final result = await reclaim.startVerification(...); } on ReclaimExpiredSessionException { - // Handle expired session -} on ReclaimVerificationManualReviewException { - // Handle manual review case -} catch (error) { - // Handle other errors if required + // Session has expired - create a new session + print('Session expired, please try again'); + +} on ReclaimVerificationDismissedException { + // User closed the verification screen + print('User cancelled verification'); + +} on ReclaimVerificationCancelledException { + // Verification was cancelled (e.g., new verification started) + print('Verification cancelled'); + +} on ReclaimVerificationPlatformNotSupportedException { + // Platform not supported (requires 64-bit runtime) + print('Platform not supported'); + +} on InvalidRequestReclaimException catch (e) { + // Invalid request parameters + print('Invalid request: ${e.message}'); + +} on ReclaimVerificationProviderException catch (e) { + // Provider-related error + print('Provider error: ${e.message}'); + +} catch (e) { + // Other errors + print('Unexpected error: $e'); } ``` -### Pre-warming +### Exception Hierarchy + +All Reclaim exceptions extend `ReclaimException`: + +- `ReclaimException` (base class) + - `ReclaimVerificationCancelledException` + - `InvalidRequestReclaimException` + - `ReclaimVerificationPlatformNotSupportedException` + - `ReclaimVerificationDismissedException` + - `ReclaimVerificationSkippedException` + - `ReclaimSessionException` + - `ReclaimExpiredSessionException` + - `ReclaimInitSessionException` + - `ReclaimVerificationProviderException` + - `ReclaimVerificationProviderNotFoundException` + - `ReclaimVerificationProviderScriptException` + - `ReclaimVerificationNoActivityDetectedException` + - `ReclaimVerificationRequirementException` + - `ReclaimVerificationProviderLoadException` + +## Session Management + +### Generating a New Session + +The recommended way to create a session: + +```dart +sessionProvider: () => ReclaimSessionInformation.generateNew( + providerId: providerId, + applicationId: appId, + applicationSecret: appSecret, +) +``` + +### Reusing Sessions -For better performance, you can pre-warm the SDK: +You can also provide existing session information: ```dart -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - ReclaimInAppSdk.preWarm(); - runApp(MyApp()); +final sessionInfo = ReclaimSessionInformation( + sessionId: 'existing-session-id', + signature: 'session-signature', + timestamp: 'session-timestamp', + version: ProviderVersionExact('1.0.0', versionExpression: '^1.0.0'), +); + +sessionProvider: () => sessionInfo +``` + +## Custom Parameters + +Some providers require additional data to complete verification. You can provide these custom parameters: + +```dart +ReclaimVerificationRequest( + applicationId: appId, + providerId: providerId, + sessionProvider: ..., + parameters: { + 'username': 'john_doe', + 'account_type': 'premium', + }, +) +``` + +These parameters are requested by the specific provider you're verifying against. Check the provider's documentation to see what parameters it requires. + +## Canceling Pending Verifications + +If you need to cancel any pending verifications: + +```dart +final reclaim = ReclaimVerification.of(context); +final wasCancelled = await reclaim.cancelPendingVerifications(); + +if (wasCancelled) { + print('Previous verification was cancelled'); } ``` -## Environment Variables -The SDK requires the following environment variables: +This is automatically handled when starting a new verification. + +## Best Practices + +### 1. Use Environment Variables + +Never hardcode credentials in production: + +```dart +// ✅ Good +const appId = String.fromEnvironment('APP_ID'); + +// ❌ Bad +const appId = 'my-app-id-123'; +``` -- `APP_ID`: Your Reclaim application ID -- `APP_SECRET`: Your application secret -- `PROVIDER_ID`: The ID of the provider to verify against +### 2. Handle All Exception Types -You can provide these values using: +Catch specific exceptions to provide better UX: -- Dart Define Env file: `--dart-define-from-file=./.env` -- Hardcoded values (not recommended for production) +```dart +try { + await reclaim.startVerification(...); +} on ReclaimExpiredSessionException { + // Show "Session expired" message +} on ReclaimVerificationDismissedException { + // User cancelled - no error message needed +} catch (e) { + // Show generic error +} +``` + +### 3. Show Loading States + +Verification can take time - show progress to users: + +```dart +setState(() => isLoading = true); +try { + final result = await reclaim.startVerification(...); + // Handle result +} finally { + setState(() => isLoading = false); +} +``` -## Example +## Next Steps -Check out the [example](example/lib/main.dart) for a complete implementation. +- Learn about [Advanced Features](/docs/flutter/advanced-features) like theming and customization +- Explore the [API Reference](/docs/flutter/api-reference) for detailed class documentation +- Check out [Examples](/docs/flutter/examples) for more use cases