Documentation Index
Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This guide covers how wallets are created and managed with the Dynamic Flutter SDK. Wallets are automatically created for users after authentication when embedded wallets are enabled in your Dynamic dashboard.
Prerequisites
Automatic Wallet Creation
When embedded wallets are enabled, wallets are automatically created for users after they authenticate. You don’t need to manually create wallets - the SDK handles this for you.
Listening for Wallet Creation
Use the userWalletsChanges stream to know when wallets are ready:
import 'dart:async';
import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:flutter/material.dart';
class WalletManager extends ChangeNotifier {
List<BaseWallet> _wallets = [];
bool _isCreatingWallets = false;
bool _creationTimedOut = false;
StreamSubscription<List<BaseWallet>>? _walletsSub;
Timer? _timeoutTimer;
List<BaseWallet> get wallets => _wallets;
bool get isCreatingWallets => _isCreatingWallets;
bool get creationTimedOut => _creationTimedOut;
WalletManager() {
_initialize();
}
void _initialize() {
// Get current wallets
_wallets = DynamicSDK.instance.wallets.userWallets;
// If user is authenticated but no wallets yet, they're being created
final token = DynamicSDK.instance.auth.token;
if (token != null && _wallets.isEmpty) {
_isCreatingWallets = true;
// Set a timeout for wallet creation
_timeoutTimer = Timer(const Duration(seconds: 15), () {
if (_wallets.isEmpty) {
_isCreatingWallets = false;
_creationTimedOut = true;
notifyListeners();
}
});
}
// Listen for wallet updates
_walletsSub = DynamicSDK.instance.wallets.userWalletsChanges.listen((newWallets) {
_wallets = newWallets;
if (newWallets.isNotEmpty) {
_isCreatingWallets = false;
_creationTimedOut = false;
_timeoutTimer?.cancel();
}
notifyListeners();
});
}
@override
void dispose() {
_walletsSub?.cancel();
_timeoutTimer?.cancel();
super.dispose();
}
}
Displaying Wallets
import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class WalletsView extends StatelessWidget {
const WalletsView({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => WalletManager(),
child: Consumer<WalletManager>(
builder: (context, walletManager, _) {
if (walletManager.isCreatingWallets) {
return const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 16),
Text('Creating wallets...'),
],
),
);
}
if (walletManager.creationTimedOut) {
return const Center(
child: Text('Wallet creation timed out. Please try again.'),
);
}
if (walletManager.wallets.isEmpty) {
return const Center(
child: Text('No wallets available'),
);
}
return ListView.builder(
itemCount: walletManager.wallets.length,
itemBuilder: (context, index) {
final wallet = walletManager.wallets[index];
return WalletCard(wallet: wallet);
},
);
},
),
);
}
}
class WalletCard extends StatelessWidget {
final BaseWallet wallet;
const WalletCard({super.key, required this.wallet});
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
wallet.walletName ?? 'Wallet',
style: Theme.of(context).textTheme.titleMedium,
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.2),
borderRadius: BorderRadius.circular(4),
),
child: Text(
wallet.chain.toUpperCase(),
style: Theme.of(context).textTheme.labelSmall,
),
),
],
),
const SizedBox(height: 8),
Text(
wallet.address,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.grey[600],
),
overflow: TextOverflow.ellipsis,
),
],
),
),
);
}
}
Using StreamBuilder
Alternatively, use StreamBuilder directly without a manager:
import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:flutter/material.dart';
class WalletsStreamView extends StatelessWidget {
const WalletsStreamView({super.key});
@override
Widget build(BuildContext context) {
return StreamBuilder<List<BaseWallet>>(
stream: DynamicSDK.instance.wallets.userWalletsChanges,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
final wallets = snapshot.data ?? [];
if (wallets.isEmpty) {
return const Center(
child: Text('No wallets available'),
);
}
return ListView.builder(
itemCount: wallets.length,
itemBuilder: (context, index) {
final wallet = wallets[index];
return ListTile(
title: Text(wallet.walletName ?? 'Wallet'),
subtitle: Text(wallet.address),
trailing: Text(wallet.chain.toUpperCase()),
);
},
);
},
);
}
}
Wallet Types
The SDK supports multiple wallet types:
EVM Wallets
For Ethereum and EVM-compatible chains (Polygon, Base, Arbitrum, etc.):
final evmWallets = DynamicSDK.instance.wallets.userWallets
.where((wallet) => wallet.chain.toUpperCase() == 'EVM')
.toList();
Solana Wallets
For Solana blockchain:
final solanaWallets = DynamicSDK.instance.wallets.userWallets
.where((wallet) => wallet.chain.toUpperCase() == 'SOL')
.toList();
Wallet Properties
Each BaseWallet has the following properties:
final wallet = DynamicSDK.instance.wallets.userWallets.first;
// Wallet address
final address = wallet.address; // "0x..." for EVM, base58 for Solana
// Chain type
final chain = wallet.chain; // "EVM" or "SOL"
// Wallet name (optional)
final name = wallet.walletName; // e.g., "turnkey"
// Wallet ID (for API operations)
final id = wallet.id; // Used for setPrimary, etc.
Setting Primary Wallet
You can set a wallet as the user’s primary wallet:
import 'package:dynamic_sdk/dynamic_sdk.dart';
Future<void> setPrimaryWallet(BaseWallet wallet) async {
final walletId = wallet.id;
if (walletId == null) {
print('Wallet has no ID');
return;
}
try {
await DynamicSDK.instance.wallets.setPrimary(walletId: walletId);
print('Primary wallet set successfully');
} catch (e) {
print('Failed to set primary wallet: $e');
}
}
Multi-Chain Support
When you have both EVM and Solana enabled in your dashboard, users will automatically get wallets for both chains:
import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:flutter/material.dart';
class MultiChainWalletsView extends StatelessWidget {
const MultiChainWalletsView({super.key});
@override
Widget build(BuildContext context) {
return StreamBuilder<List<BaseWallet>>(
stream: DynamicSDK.instance.wallets.userWalletsChanges,
builder: (context, snapshot) {
final wallets = snapshot.data ?? [];
final evmWallets = wallets
.where((w) => w.chain.toUpperCase() == 'EVM')
.toList();
final solanaWallets = wallets
.where((w) => w.chain.toUpperCase() == 'SOL')
.toList();
return ListView(
children: [
if (evmWallets.isNotEmpty) ...[
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'EVM Wallets',
style: Theme.of(context).textTheme.titleLarge,
),
),
...evmWallets.map((wallet) => WalletCard(wallet: wallet)),
],
if (solanaWallets.isNotEmpty) ...[
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'Solana Wallets',
style: Theme.of(context).textTheme.titleLarge,
),
),
...solanaWallets.map((wallet) => WalletCard(wallet: wallet)),
],
],
);
},
);
}
}
Manual Wallet Access
You can also access wallets directly without streams:
import 'package:dynamic_sdk/dynamic_sdk.dart';
// Get current wallets
final wallets = DynamicSDK.instance.wallets.userWallets;
if (wallets.isEmpty) {
print('No wallets available');
} else {
print('User has ${wallets.length} wallet(s)');
for (final wallet in wallets) {
print('${wallet.chain}: ${wallet.address}');
}
}
Dashboard Configuration
To enable embedded wallets:
- Go to your Dynamic Dashboard
- Navigate to Wallets settings
- Toggle “Embedded Wallets” on
- Select the chains you want to support:
- Enable “EVM” for Ethereum and compatible chains
- Enable “Solana” for Solana blockchain
- Save your changes
Next Steps
After wallets are created, you can:
Reference
For more details on wallet management: