Prerequisites
- SDK initialized
- User authenticated
- Embedded wallets enabled in dashboard
Listening for Wallet Creation
Use theuserWalletsChanges Flow to know when wallets are ready:
Copy
Ask AI
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.dynamic.sdk.android.DynamicSDK
import com.dynamic.sdk.android.Models.BaseWallet
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
class WalletManager : ViewModel() {
private val sdk = DynamicSDK.getInstance()
private var walletCreationTimer: Job? = null
private val _wallets = MutableStateFlow<List<BaseWallet>>(emptyList())
val wallets: StateFlow<List<BaseWallet>> = _wallets.asStateFlow()
private val _isCreatingWallets = MutableStateFlow(false)
val isCreatingWallets: StateFlow<Boolean> = _isCreatingWallets.asStateFlow()
init {
startListening()
}
private fun startListening() {
// Get current wallets
_wallets.value = sdk.wallets.userWallets
// If user is authenticated but no wallets yet, they're being created
if (sdk.auth.isAuthenticated() && _wallets.value.isEmpty()) {
_isCreatingWallets.value = true
// Set a timeout for wallet creation
walletCreationTimer = viewModelScope.launch {
delay(15000) // 15 seconds
if (_wallets.value.isEmpty()) {
_isCreatingWallets.value = false
}
}
}
// Listen for wallet updates
viewModelScope.launch {
sdk.wallets.userWalletsChanges.collect { newWallets ->
_wallets.value = newWallets
if (newWallets.isNotEmpty()) {
_isCreatingWallets.value = false
walletCreationTimer?.cancel()
}
}
}
}
}
Displaying Wallets
Copy
Ask AI
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.dynamic.sdk.android.Models.BaseWallet
@Composable
fun WalletsScreen(viewModel: WalletManager) {
val wallets by viewModel.wallets.collectAsState()
val isCreatingWallets by viewModel.isCreatingWallets.collectAsState()
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
Text(
text = "My Wallets",
style = MaterialTheme.typography.headlineMedium
)
Spacer(modifier = Modifier.height(16.dp))
when {
isCreatingWallets -> {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = androidx.compose.ui.Alignment.CenterVertically
) {
CircularProgressIndicator()
Text("Creating wallets...")
}
}
wallets.isEmpty() -> {
Text("No wallets available")
}
else -> {
LazyColumn {
items(wallets) { wallet ->
WalletCard(wallet)
}
}
}
}
}
}
@Composable
fun WalletCard(wallet: BaseWallet) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = androidx.compose.ui.Alignment.CenterVertically
) {
Text(
text = wallet.walletName ?: "Wallet",
style = MaterialTheme.typography.titleMedium
)
Surface(
color = MaterialTheme.colorScheme.primaryContainer,
shape = MaterialTheme.shapes.small
) {
Text(
text = wallet.chain.uppercase(),
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
}
}
Spacer(modifier = Modifier.height(8.dp))
Text(
text = wallet.address,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1
)
}
}
}
Wallet Types
The SDK supports multiple wallet types:EVM Wallets
For Ethereum and EVM-compatible chains (Polygon, Base, Arbitrum, etc.):Copy
Ask AI
val evmWallets = sdk.wallets.userWallets.filter {
it.chain.uppercase() == "EVM"
}
Solana Wallets
For Solana blockchain:Copy
Ask AI
val solanaWallets = sdk.wallets.userWallets.filter {
it.chain.uppercase() == "SOL"
}
Wallet Properties
EachBaseWallet has the following properties:
Copy
Ask AI
val wallet: BaseWallet
// Wallet address
val address = wallet.address // "0x..." for EVM, base58 for Solana
// Chain type
val chain = wallet.chain // "EVM" or "SOL"
// Wallet name (optional)
val name = wallet.walletName // e.g., "turnkey"
// Wallet ID (for API operations)
val id = wallet.id // Used for setPrimary, etc.
Setting Primary Wallet
You can set a wallet as the user’s primary wallet:Copy
Ask AI
import com.dynamic.sdk.android.DynamicSDK
import com.dynamic.sdk.android.Models.BaseWallet
val sdk = DynamicSDK.getInstance()
fun setPrimaryWallet(wallet: BaseWallet) {
val walletId = wallet.id ?: return
try {
sdk.wallets.setPrimary(walletId)
println("Primary wallet set successfully")
} catch (e: Exception) {
println("Failed to set primary wallet: ${e.message}")
}
}
Multi-Chain Support
When you have both EVM and Solana enabled in your dashboard, users will automatically get wallets for both chains:Copy
Ask AI
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.dynamic.sdk.android.Models.BaseWallet
@Composable
fun MultiChainWalletsScreen(wallets: List<BaseWallet>) {
val evmWallets = wallets.filter { it.chain.uppercase() == "EVM" }
val solanaWallets = wallets.filter { it.chain.uppercase() == "SOL" }
LazyColumn(modifier = Modifier.fillMaxSize().padding(16.dp)) {
// EVM Wallets Section
if (evmWallets.isNotEmpty()) {
item {
Text(
text = "EVM Wallets",
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(vertical = 8.dp)
)
}
items(evmWallets) { wallet ->
WalletCard(wallet)
}
}
// Solana Wallets Section
if (solanaWallets.isNotEmpty()) {
item {
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Solana Wallets",
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(vertical = 8.dp)
)
}
items(solanaWallets) { wallet ->
WalletCard(wallet)
}
}
}
}
@Composable
fun WalletCard(wallet: BaseWallet) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = wallet.walletName ?: "Wallet",
style = MaterialTheme.typography.titleMedium
)
Text(
text = wallet.address,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}