Create and manage pregenerated wallets for users in Flutter applications
Paraโs Wallet Pregeneration feature allows you to create wallets for users before they authenticate, giving you control over when and how users claim ownership of their wallets. This is particularly powerful in mobile applications, where you can leverage device-specific storage capabilities for enhanced user experiences.
Pregeneration is especially valuable for devices that may not have full WebAuthn support for passkeys. It allows you to create Para wallets for users on any device while managing the security of the wallet yourself.
In Flutter, you can create pregenerated wallets of multiple types with a single method call:
Copy
Ask AI
import 'package:para/para.dart';Future<List<Wallet>> createPregenWallets() async { final pregenWalletsFuture = para.createPregenWalletPerType( pregenId: {'EMAIL': 'user@example.com'}, // Map format for pregen ID types: [WalletType.evm], // Optionally specify wallet types ); final pregenWallets = await pregenWalletsFuture.future; // Get the user share final userShareFuture = para.getUserShare(); final userShare = await userShareFuture.future; // Store user share securely (see storage options below) return pregenWallets;}
import 'package:encrypted_shared_preferences/encrypted_shared_preferences.dart';final encryptedPrefs = EncryptedSharedPreferences();// Store the user shareFuture<void> storeUserShare(String userShare) async { try { await encryptedPrefs.setString('para_user_share', userShare); } catch (e) { // Handle error }}// Retrieve the user shareFuture<String?> retrieveUserShare() async { try { return await encryptedPrefs.getString('para_user_share'); } catch (e) { // Handle error return null; }}
Whichever storage method you choose, ensure you implement proper security measures. The user share is critical for wallet access, and if lost, the wallet becomes permanently inaccessible.
Once you have created a pregenerated wallet and stored the user share, you can use it for signing operations:
Copy
Ask AI
import 'dart:convert';import 'package:para/para.dart';Future<String> usePregenWallet(String walletId) async { // Retrieve the user share from your secure storage final userShare = await retrieveUserShare(); if (userShare == null) { throw Exception("User share not found"); } // Load the user share into the Para client await para.setUserShare(userShare); // Now you can perform signing operations final messageBase64 = base64Encode(utf8.encode("Hello, World!")); final signatureFuture = para.signMessage( walletId: walletId, messageBase64: messageBase64, ); final signatureResult = await signatureFuture.future; return signatureResult.signature;}
Create wallets that are bound to a specific device by using device-specific identifiers combined with secure local storage. This approach is ideal for multi-device users who need different wallets for different devices.
Copy
Ask AI
import 'package:device_info_plus/device_info_plus.dart';import 'package:para/para.dart';Future<List<Wallet>> createDeviceWallet() async { final deviceInfo = DeviceInfoPlugin(); String deviceId; if (Platform.isAndroid) { final androidInfo = await deviceInfo.androidInfo; deviceId = androidInfo.id; } else if (Platform.isIOS) { final iosInfo = await deviceInfo.iosInfo; deviceId = iosInfo.identifierForVendor ?? 'unknown'; } else { deviceId = 'unknown'; } final pregenWalletsFuture = para.createPregenWalletPerType( pregenId: {'CUSTOM_ID': 'device-$deviceId'}, ); final pregenWallets = await pregenWalletsFuture.future; // Store the user share in device-specific secure storage final userShare = await para.getUserShare().future; await storeUserShare(userShare); return pregenWallets;}
Seamlessly introduce blockchain functionality to your existing app users without requiring them to understand wallets or crypto.
When a user is ready to take ownership of their pregenerated wallet, they can claim it once theyโve authenticated with Para:
Copy
Ask AI
import 'package:para/para.dart';Future<String> claimWallet(Map<String, String> pregenId) async { // Ensure user is authenticated if (!(await para.isSessionActive().future)) { throw Exception("User must be authenticated to claim wallets"); } // Retrieve and load the user share final userShare = await retrieveUserShare(); if (userShare != null) { await para.setUserShare(userShare); } // Claim the wallet with the pregen ID final claimFuture = para.claimPregenWallets( pregenId: pregenId, // e.g., {'EMAIL': 'user@example.com'} ); final recoverySecret = await claimFuture.future; // Optionally, clear the locally stored user share after claiming // since Para now manages it through the user's authentication await clearUserShare(); return recoverySecret;}
After claiming, Para will manage the user share through the userโs authentication methods. You can safely remove the user share from your local storage if you no longer need to access the wallet directly.
Utilize Device Security: Leverage biometric authentication (TouchID/FaceID) to protect access to locally stored user shares.
Implement Device Sync: For users with multiple devices, consider implementing your own synchronization mechanism for user shares across devices.
Handle Offline States: Mobile applications often work offline. Design your pregenerated wallet system to function properly even when connectivity is limited.
Backup Strategies: Provide users with options to back up their wallet data, especially for device-specific wallets that might not be associated with their Para account.
Clear Security Boundaries: Clearly communicate to users when theyโre using an app-managed wallet versus a personally-owned wallet.