privy_flutter 0.4.0
privy_flutter: ^0.4.0 copied to clipboard
Privy Flutter SDK enables seamless authentication, wallet management, and identity verification for Flutter apps with native iOS and Android support.
Privy Flutter SDK #
The Privy Flutter SDK is a Flutter plugin that connects your application to native Privy SDKs for iOS and Android. It enables authentication, non-custodial embedded wallets, and user management by leveraging Privy's platform-specific capabilities.
Features #
Authentication #
- Login with Phone
- Login with Email
- Login with Custom Auth
- Login with OAuth (Google, Apple, Twitter, Discord)
- Login with SIWE (Sign-In with Ethereum)
Embedded Wallets (Ethereum & Solana) #
- Wallet Creation
- Automatic Recovery
- Signing Messages & Transactions
Ethereum-Only Features
- Broadcasting Transactions
- Multiple Embedded Wallets
Getting Started #
Requirements #
- Flutter: 3.24.0+
- Dart: 3.0.0+
- Android: API 27+ (8.1 Oreo or newer)
- iOS: 16+
Installation #
Add the latest Privy SDK dependency to your pubspec.yaml
:
dependencies:
flutter:
sdk: flutter
privy_flutter: ^0.0.1 # Replace with the latest version
Run:
flutter pub get
Configuration #
Registering Your App #
You must configure your App ID and Client ID in the Privy Developer Dashboard.
- iOS: Add your app's Bundle Identifier under Settings → Clients.
- Android: Add your Application ID from
build.gradle
. - Register Allowed URL Schemes for OAuth authentication in
Info.plist
(iOS) andAndroidManifest.xml
(Android).
Initialization #
Import and configure Privy in your Flutter app:
import 'package:privy_flutter/privy_flutter.dart';
final privyConfig = PrivyConfig(
appId: "YOUR_APP_ID",
appClientId: "YOUR_CLIENT_ID",
);
final privy = Privy(config: privyConfig);
Get the Current Authentication State #
When the Privy SDK is initialized, the user's authentication state will be set to NotReady until Privy finishes initialization. During this time, we suggest you show a loading state to your user. For you convenience, we've added a suspending getAuthState() function. Here's an example with some pseudocode:
await privy.getAuthState();
Authentication #
Login with Email #
Authenticate users via email-based OTP verification.
Step 1: Send OTP to User’s Email
final result = await privy.email.sendCode("user@example.com");
- Success(): OTP was sent successfully.
- Failure(PrivyException): Error sending OTP.
Step 2: Verify OTP and Login
final loginResult = await privy.email.loginWithCode(code: "123456", email: "user@example.com");
- Success(PrivyUser): User authenticated successfully.
- Failure(PrivyException): Invalid OTP or authentication failed.
Link Email to Existing Account
final linkResult = await privy.email.linkWithCode(code: "123456", email: "user@example.com");
- Success(): Email linked successfully to current user.
- Failure(PrivyException): Invalid OTP, user not authenticated, or linking failed.
Update User's Email
final updateResult = await privy.email.updateWithCode(code: "123456", email: "newemail@example.com");
- Success(): Email updated successfully.
- Failure(PrivyException): Invalid OTP, user not authenticated, or update failed.
Login with Phone #
Authenticate users via SMS-based OTP verification.
Step 1: Send OTP to User’s Phone Number
final result = await privy.sms.sendCode("+14155552671");
- Success(): OTP was sent successfully.
- Failure(PrivyException): Error sending OTP.
Step 2: Verify OTP and Login
final loginResult = await privy.sms.loginWithCode(code: "123456", phoneNumber: "+14155552671");
- Success(PrivyUser): User authenticated successfully.
- Failure(PrivyException): Invalid OTP or authentication failed.
Link Phone Number to Existing Account
final linkResult = await privy.sms.linkWithCode(code: "123456", phoneNumber: "+14155552671");
- Success(): Phone number linked successfully to current user.
- Failure(PrivyException): Invalid OTP, user not authenticated, or linking failed.
Update User's Phone Number
final updateResult = await privy.sms.updateWithCode(code: "123456", phoneNumber: "+14155559999");
- Success(): Phone number updated successfully.
- Failure(PrivyException): Invalid OTP, user not authenticated, or update failed.
Login with Custom Auth #
Authenticate users using a third-party authentication provider.
final loginResult = await privy.customAuth.loginWithCustomAccessToken();
- Success(PrivyUser): User authenticated successfully.
- Failure(PrivyException): Invalid or expired token.
Login with OAuth #
The Flutter SDK supports OAuth login with Google, Apple, Twitter, and Discord. For all other OAuth providers, use JWT-based authentication.
Platform Configuration
Android: Add to android/app/src/main/AndroidManifest.xml
:
<activity
android:name="io.privy.sdk.oAuth.PrivyRedirectActivity"
android:exported="true"
android:launchMode="singleTask"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="YOUR_CUSTOM_PRIVY_OAUTH_SCHEME" />
</intent-filter>
</activity>
iOS: Add to ios/Runner/Info.plist
:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>privy.oauth</string>
<key>CFBundleURLSchemes</key>
<array>
<string>YOUR_CUSTOM_PRIVY_OAUTH_SCHEME</string>
</array>
</dict>
</array>
Note: Apple Sign In requires iOS 13.0+ and additional configuration in Xcode (Sign in with Apple capability). It is only available on iOS, not on Android Devices.
Usage
final result = await privy.oAuth.login(
provider: OAuthProvider.google, // .google, .apple, .twitter, .discord
appUrlScheme: 'your-app-scheme',
);
result.fold(
onSuccess: (user) => print('Login successful: ${user.id}'),
onFailure: (error) => print('Login failed: $error'),
);
Login with SIWE (Sign-In with Ethereum) #
Authenticate users by having them sign a SIWE message with their Ethereum wallet.
Step 1: Generate SIWE Message
final params = SiweMessageParams(
appDomain: "your-app.com",
appUri: "https://your-app.com",
chainId: "1", // Ethereum mainnet
walletAddress: "0x...", // User's wallet address
);
final messageResult = await privy.siwe.generateSiweMessage(params);
Step 2: Have User Sign Message & Login
// User signs the message with their wallet (outside of Privy)
final signature = "0x..."; // Signature from user's wallet
final loginResult = await privy.siwe.loginWithSiwe(
message: message,
signature: signature,
params: params,
metadata: WalletLoginMetadata(
walletClientType: WalletClientType.metamask,
connectorType: "wallet_connect",
),
);
- Success(PrivyUser): User authenticated successfully.
- Failure(PrivyException): Invalid signature or authentication failed.
Get Access Token #
Retrieve the user's authentication token for API requests.
final user = await privy.getUser();
final getAccessTokenResult = await user?.getAccessToken();
- Success(String): Token retrieved successfully.
- Failure(PrivyException): User not authenticated or error occurred.
Refresh User Data #
Manually refresh the user data to ensure you have the latest information.
final user = await privy.getUser();
final refreshResult = await user?.refresh();
- Success(void): User data refreshed successfully.
- Failure(PrivyException): Error occurred while refreshing user data.
Embedded Wallets #
Create an Ethereum Wallet #
Creates a non-custodial Ethereum embedded wallet for the user.
final user = await privy.getUser();
final walletResult = await user?.createEthereumWallet();
- Success(EmbeddedEthereumWallet): Wallet created successfully.
- Failure(PrivyException): User not authenticated, network error, or wallet limit exceeded.
Create a Solana Wallet #
Creates a non-custodial Solana embedded wallet for the user. You can create multiple wallets by setting createAdditional
to true.
final user = await privy.getUser();
// Create initial wallet
final walletResult = await user?.createSolanaWallet();
// Create additional wallet
final additionalWalletResult = await user?.createSolanaWallet(createAdditional: true);
- Success(EmbeddedSolanaWallet): Wallet created successfully.
- Failure(PrivyException): User not authenticated or network error.
Sign a Message (Solana) #
Sign a message using the user’s Solana embedded wallet.
final user = await privy.getUser();
final signature = await user?.embeddedSolanaWallets.first.provider.signMessage("message");
- Success(String): Signature generated successfully.
- Failure(PrivyException): User not authenticated or wallet not found.
Logout #
Logs the user out and clears the persisted session.
await privy.logout();
- Success(): User logged out successfully.
- Failure(PrivyException): Error during logout.
Error Handling #
All SDK responses use Result<T>
. Handle success or failure using either .fold()
or a switch
statement.
Using .fold()
#
The .fold()
method allows you to execute separate callbacks for success and failure.
result.fold(
onSuccess: (user) => print("Success: ${user.id}"),
onFailure: (error) => print("Error: ${error.message}"),
);
Using a switch
Statement #
Alternatively, you can use a switch
statement to handle success and failure.
switch (result) {
case Success(:final user): // Extracts `user` from Success<T>
print("Success: ${user.id}");
break;
case Failure(:final error): // Extracts `error` from Failure<T>
print("Error: ${error.message}");
break;
}
License #
This project is licensed under the MIT License.
For more details, visit the Privy Developer Dashboard.