Bugfix on startup profile loading

This commit is contained in:
Kgothatso Ngako
2026-06-30 01:02:20 +02:00
parent c47751ad55
commit 91b9c14992
8 changed files with 146 additions and 101 deletions

View File

@@ -5,6 +5,7 @@ import androidx.room3.Insert
import androidx.room3.Query
import androidx.room3.Transaction
import androidx.room3.Upsert
import at.torch.compose.database.model.intermdiate.LocalAccount
import kotlinx.coroutines.flow.Flow
@Dao
@@ -26,7 +27,11 @@ interface UnsignedNostrEventDao {
@Transaction
@Query("SELECT * FROM UnsignedNostrEvent WHERE kind = 0 AND pubKey = :publicKey")
fun observeProfile(publicKey: String): Flow<at.torch.compose.database.model.intermdiate.LocalAccount?>
fun observeProfile(publicKey: String): Flow<LocalAccount?>
@Transaction
@Query("SELECT * FROM UnsignedNostrEvent WHERE kind = 0")
fun getLocalAccounts(): List<LocalAccount>
@Query("SELECT * FROM UnsignedNostrEvent WHERE pubKey = :publicKey AND signedAt IS NULL")
fun observeUnsignedNostrEvents(publicKey: String): Flow<at.torch.compose.database.model.UnsignedNostrEvent?>

View File

@@ -1,7 +1,7 @@
package at.torch.compose.database.repository
import at.torch.compose.database.model.Profile
import at.torch.compose.database.model.UnsignedNostrEvent
import at.torch.compose.database.model.intermdiate.LocalAccount
import at.torch.compose.nostr.Relays
import co.touchlab.kermit.Logger
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageEvent
@@ -72,6 +72,10 @@ class DatabaseNostrRepository(
val logger = Logger.withTag(TAG)
override suspend fun getLocalAccounts(): List<LocalAccount> {
return database.unsignedNostrEventDao().getLocalAccounts()
}
override suspend fun observeProfile(publicKey: HexKey): Flow<at.torch.compose.database.model.intermdiate.LocalAccount?> {
return database.unsignedNostrEventDao().observeProfile(publicKey)
}

View File

@@ -1,5 +1,6 @@
package at.torch.compose.repository
import at.torch.compose.database.model.intermdiate.LocalAccount
import com.vitorpamplona.quartz.marmot.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.Kind
@@ -7,6 +8,8 @@ import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import kotlinx.coroutines.flow.Flow
interface NostrRepository {
suspend fun getLocalAccounts(): List<LocalAccount>
suspend fun observeProfile(publicKey: HexKey): Flow<at.torch.compose.database.model.intermdiate.LocalAccount?>
suspend fun observeRelation(publicKey: HexKey, activePublicKey: HexKey): Flow<List<at.torch.compose.database.model.Connection>>
@@ -121,6 +124,10 @@ interface NostrRepository {
companion object {
val NO_OP_NOSTR_REPOSITORY = object : NostrRepository {
override suspend fun getLocalAccounts(): List<LocalAccount> {
TODO("Not yet implemented")
}
override suspend fun observeProfile(publicKey: HexKey): Flow<at.torch.compose.database.model.intermdiate.LocalAccount?> {
TODO("Not yet implemented")
}

View File

@@ -16,6 +16,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import at.torch.compose.ui.composable.widgets.LoadingDataIndicator
import fr.acinq.phoenix.data.ListWalletState
import fr.acinq.phoenix.data.UserWallet
import fr.acinq.phoenix.data.WalletId
@@ -31,7 +32,7 @@ fun SovereignWalletStartupScreen(
sovereignWalletViewModel: at.torch.compose.ui.view.model.SovereignWalletViewModel,
onNavigateToWalletIntroPage: () -> Unit,
onNavigateToWalletLandingPage: () -> Unit,
onNavigateToWalletDashboard: () -> Unit,
onSuccessfulStartup: () -> Unit,
forceWalletId: WalletId?,
) {
val sovereignWalletStartupViewModel = viewModel<at.torch.compose.ui.view.model.SovereignWalletStartupViewModel>(
@@ -53,7 +54,7 @@ fun SovereignWalletStartupScreen(
) {
when (sovereignWalletViewModel.listWalletState.value) {
is ListWalletState.Init -> {
_root_ide_package_.at.torch.compose.ui.composable.widgets.LoadingDataIndicator(
LoadingDataIndicator(
text = "Decrypting..."
)
}
@@ -81,22 +82,22 @@ fun SovereignWalletStartupScreen(
when {
availableWallets.isEmpty() -> {
LaunchedEffect(Unit) { onNavigateToWalletLandingPage.invoke() }
_root_ide_package_.at.torch.compose.ui.composable.widgets.LoadingDataIndicator(
LoadingDataIndicator(
text = "Initializing..."
)
}
availableWalletMetadata == null || defaultWallet.value == null -> {
_root_ide_package_.at.torch.compose.ui.composable.widgets.LoadingDataIndicator(
LoadingDataIndicator(
text = "Preparing wallet..."
)
}
activeWallet != null -> {
_root_ide_package_.at.torch.compose.ui.composable.widgets.LoadingDataIndicator(
LoadingDataIndicator(
text = "Opening Wallet"
)
LaunchedEffect(Unit) {
sovereignWalletViewModel.loadSovereignData(activeWallet.id)
onNavigateToWalletDashboard.invoke()
onSuccessfulStartup.invoke()
}
}
else -> {
@@ -155,7 +156,7 @@ fun SovereignWalletStartupScreen(
doLoadWallet = { userWallet ->
sovereignWalletStartupViewModel.startupNode(walletId = userWallet.walletId, words = userWallet.words, onStartupSuccess = {
sovereignWalletViewModel.setActiveWallet(walletId = userWallet.walletId, business = it)
onNavigateToWalletDashboard.invoke()
onSuccessfulStartup.invoke()
})
loadingWallet = null
},
@@ -168,12 +169,12 @@ fun SovereignWalletStartupScreen(
}
}
is at.torch.compose.ui.view.model.StartupViewState.StartingBusiness -> {
_root_ide_package_.at.torch.compose.ui.composable.widgets.LoadingDataIndicator(
LoadingDataIndicator(
text = "Starting wallet"
)
}
is at.torch.compose.ui.view.model.StartupViewState.BusinessActive -> {
_root_ide_package_.at.torch.compose.ui.composable.widgets.LoadingDataIndicator(
LoadingDataIndicator(
text = "Opening wallet"
)
}
@@ -235,10 +236,10 @@ private fun BoxScope.LoadWallet(
when (isScreenLockRequired.value) {
null -> {
_root_ide_package_.at.torch.compose.ui.composable.widgets.LoadingDataIndicator(text = "Loading preferences...")
LoadingDataIndicator(text = "Loading preferences...")
}
true -> {
_root_ide_package_.at.torch.compose.ui.composable.widgets.LoadingDataIndicator(text = "Unlock to continue")
LoadingDataIndicator(text = "Unlock to continue")
ScreenLockPrompt(
walletId = userWallet.walletId,
walletName = metadata.nameOrDefault(),
@@ -250,7 +251,7 @@ private fun BoxScope.LoadWallet(
)
}
false -> {
_root_ide_package_.at.torch.compose.ui.composable.widgets.LoadingDataIndicator(text = "Starting wallet...")
LoadingDataIndicator(text = "Starting wallet...")
LaunchedEffect(Unit) {
doLoadWallet(userWallet)
}

View File

@@ -18,7 +18,10 @@ import at.torch.compose.ui.composable.ChatRoomDetailScreen
import at.torch.compose.ui.composable.HomeScreen
import at.torch.compose.ui.composable.UnsyncedProfileScreen
import at.torch.compose.ui.composable.navigation.routes.ChatRoomCreationRoute
import at.torch.compose.ui.composable.navigation.routes.LoadingRoute
import at.torch.compose.ui.composable.navigation.routes.SovereignWalletStartupRoute
import at.torch.compose.ui.composable.navigation.routes.WriteNewNoteRoute
import at.torch.compose.ui.view.state.NavigationUIState
import co.touchlab.kermit.Logger
import fr.acinq.phoenix.PhoenixGlobal
import kotlinx.coroutines.CoroutineExceptionHandler
@@ -77,7 +80,7 @@ fun TorchNavHost(
val navigationViewModel: at.torch.compose.ui.view.model.NavigationViewModel = viewModel (
factory = at.torch.compose.ui.view.model.NavigationViewModel.factory(
activeWallet = sovereignWalletViewModel.activeWalletInUI,
initialNavigationUIState = at.torch.compose.ui.view.state.NavigationUIState.Loading(),
initialNavigationUIState = NavigationUIState.Loading(),
nostrRepository = databaseNostrRepository,
scope = applicationIOScope
)
@@ -85,7 +88,7 @@ fun TorchNavHost(
val notaryViewModel: at.torch.compose.ui.view.model.NotaryViewModel = viewModel(
factory = at.torch.compose.ui.view.model.NotaryViewModel.Companion.factory(
factory = at.torch.compose.ui.view.model.NotaryViewModel.factory(
activeWalletStateFlow = sovereignWalletViewModel.activeWalletInUI,
nostrRepository = databaseNostrRepository,
chatRepository = databaseChatRepository,
@@ -94,7 +97,7 @@ fun TorchNavHost(
)
// TODO: Produce a notary UI Element...
val synchronizationViewModel: at.torch.compose.ui.view.model.SynchronizationViewModel = viewModel(
factory = at.torch.compose.ui.view.model.SynchronizationViewModel.Companion.factory(
factory = at.torch.compose.ui.view.model.SynchronizationViewModel.factory(
activeWalletStateFlow = sovereignWalletViewModel.activeWalletInUI,
nostrRepository = databaseNostrRepository,
chatRepository = databaseChatRepository,
@@ -107,7 +110,7 @@ fun TorchNavHost(
LaunchedEffect(lifecycleOwner) {
navigationViewModel.navigationUIState.collect { state ->
when (state) {
is at.torch.compose.ui.view.state.NavigationUIState.Error -> {
is NavigationUIState.Error -> {
navController.navigate(
route = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.ImplementationPendingRoute(
"Error screen"
@@ -116,14 +119,14 @@ fun TorchNavHost(
popUpTo(0)
}
}
is at.torch.compose.ui.view.state.NavigationUIState.StartupPhoenix -> {
is NavigationUIState.StartupPhoenix -> {
navController.navigate(
route = at.torch.compose.ui.composable.navigation.routes.SovereignWalletStartupRoute
route = SovereignWalletStartupRoute
) {
popUpTo(0)
}
}
is at.torch.compose.ui.view.state.NavigationUIState.Loading -> {
is NavigationUIState.Loading -> {
navController.navigate(
route = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.LoadingRoute(
text = state.text
@@ -132,14 +135,14 @@ fun TorchNavHost(
popUpTo(0)
}
}
is at.torch.compose.ui.view.state.NavigationUIState.Landing -> {
is NavigationUIState.Landing -> {
navController.navigate(
route = at.torch.compose.ui.composable.navigation.routes.LandingRoute
) {
popUpTo(0)
}
}
is at.torch.compose.ui.view.state.NavigationUIState.UnsignedProfile -> {
is NavigationUIState.UnsignedProfile -> {
navController.navigate(
route = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.UnsignedProfileRoute(
state.unsignedNostrEvent.id
@@ -148,7 +151,7 @@ fun TorchNavHost(
popUpTo(0)
}
}
is at.torch.compose.ui.view.state.NavigationUIState.UnsyncedProfile -> {
is NavigationUIState.UnsyncedProfile -> {
navController.navigate(
route = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.UnsyncedProfileRoute(
state.unsignedNostrEvent.pubKey
@@ -157,7 +160,7 @@ fun TorchNavHost(
popUpTo(0)
}
}
is at.torch.compose.ui.view.state.NavigationUIState.UnqueuedProfileSynchronization -> {
is NavigationUIState.UnqueuedProfileSynchronization -> {
navController.navigate(
route = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.UnqueuedProfileSynchronizationRoute(
unsignedNostrEventId = state.unsignedNostrEvent.id,
@@ -167,7 +170,7 @@ fun TorchNavHost(
popUpTo(0)
}
}
is at.torch.compose.ui.view.state.NavigationUIState.UnindexedProfile -> {
is NavigationUIState.UnindexedProfile -> {
navController.navigate(
route = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.UnindexedProfileRoute(
state.nostrEvent.id
@@ -176,14 +179,14 @@ fun TorchNavHost(
popUpTo(0)
}
}
is at.torch.compose.ui.view.state.NavigationUIState.UnqueuedProfile -> {
is NavigationUIState.UnqueuedProfile -> {
navController.navigate(
route = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.UnqueuedProfileRoute(
state.profile.nostrEventId
)
)
}
is at.torch.compose.ui.view.state.NavigationUIState.UnannouncedProfile -> {
is NavigationUIState.UnannouncedProfile -> {
navController.navigate(
route = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.UnannouncedProfileRoute(
state.broadcastNostrEventRequest.nostrEventId
@@ -192,7 +195,7 @@ fun TorchNavHost(
popUpTo(0)
}
}
is at.torch.compose.ui.view.state.NavigationUIState.ProfileLoaded -> {
is NavigationUIState.ProfileLoaded -> {
navController.navigate(
route = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.SocialPreconditionRoute(
activeUserPubkey = state.publicKey
@@ -218,28 +221,28 @@ fun TorchNavHost(
navController = navController,
startDestination = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.LoadingRoute()
) {
composable<at.torch.compose.ui.composable.navigation.routes.SovereignWalletStartupRoute> {
composable<SovereignWalletStartupRoute> {
_root_ide_package_.at.torch.compose.ui.composable.SovereignWalletStartupScreen(
sovereignWalletViewModel = sovereignWalletViewModel,
onNavigateToWalletLandingPage = {
navController.navigate(
route = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.LoadingRoute(
route = LoadingRoute(
text = "Loading Aux"
)
)
},
onNavigateToWalletIntroPage = {
navController.navigate(
route = at.torch.compose.ui.composable.navigation.routes.LandingRoute
)
},
onNavigateToWalletDashboard = {
navController.navigate(
route = _root_ide_package_.at.torch.compose.ui.composable.navigation.routes.LoadingRoute(
text = "Opening Aux"
route = LoadingRoute(
text = "Introducing... Aux"
)
)
},
onSuccessfulStartup = {
applicationIOScope.launch {
navigationViewModel.loadNostrProfile()
}
},
forceWalletId = null,
)
}
@@ -292,7 +295,7 @@ fun TorchNavHost(
sovereignWalletViewModel.listAvailableWallets {
sovereignWalletViewModel.switchToWallet(walletId)
navController.navigate(
route = at.torch.compose.ui.composable.navigation.routes.SovereignWalletStartupRoute
route = SovereignWalletStartupRoute
)
}
}

View File

@@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import at.torch.compose.ui.view.state.NavigationUIState
import co.touchlab.kermit.Logger
import fr.acinq.phoenix.data.ActiveWallet
import fr.acinq.phoenix.managers.nostrPublicKey
@@ -18,10 +19,11 @@ import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.launch
import kotlin.time.Duration.Companion.milliseconds
class NavigationViewModel(
val activeWalletStateFlow: StateFlow<ActiveWallet?>,
initialNavigationUIState: at.torch.compose.ui.view.state.NavigationUIState,
initialNavigationUIState: NavigationUIState,
val nostrRepository: at.torch.compose.repository.NostrRepository,
val scope: CoroutineScope,
): ViewModel() {
@@ -31,7 +33,7 @@ class NavigationViewModel(
fun factory(
activeWallet: StateFlow<ActiveWallet?>,
initialNavigationUIState: at.torch.compose.ui.view.state.NavigationUIState,
initialNavigationUIState: NavigationUIState,
nostrRepository: at.torch.compose.repository.NostrRepository,
scope: CoroutineScope,
): ViewModelProvider.Factory = viewModelFactory {
@@ -57,87 +59,106 @@ class NavigationViewModel(
observeProfile()
}
suspend fun loadNostrProfile() {
val activeUserPublicKey = nostrRepository.getLocalAccounts().firstOrNull()?.profile?.publicKey
if (activeUserPublicKey == null) {
// TODO: We can just go directly to startup witout fear...
_navigationUIState.getAndUpdate {
NavigationUIState.Landing
}
} else {
// _navigationUIState.getAndUpdate {
// NavigationUIState.Loading(text = "Getting profile ready")
// }
loadNostrProfile(activeUserPublicKey)
}
}
private suspend fun loadNostrProfile(activeUserPublicKey: String) {
nostrRepository.observeProfile(
publicKey = activeUserPublicKey
).distinctUntilChanged().collect { localProfile ->
logger.i("Local Profile: $localProfile")
_navigationUIState.getAndUpdate {
if (localProfile == null) {
logger.i("We need to be on the landing screen so user creates account")
NavigationUIState.Landing
} else if (localProfile.unsignedNostrEvent == null) {
logger.i("We need to be on the landing screen so user creates account")
NavigationUIState.Landing
} else if (localProfile.broadcastNostrEventReceipt != null) {
logger.i("We have a broadcast receipt: ${localProfile.profile}")
NavigationUIState.ProfileLoaded(
publicKey = localProfile.unsignedNostrEvent.pubKey
)
} else if (localProfile.unsignedNostrEvent.signedAt != null && localProfile.profile != null) {
logger.i("We have successfully synced a profile: ${localProfile.profile}")
NavigationUIState.ProfileLoaded(
publicKey = localProfile.unsignedNostrEvent.pubKey
)
} else if (localProfile.broadcastNostrEventRequest != null) {
logger.i("We have a broadcast request: ${localProfile.broadcastNostrEventRequest}")
NavigationUIState.UnannouncedProfile(
broadcastNostrEventRequest = localProfile.broadcastNostrEventRequest
)
} else if (localProfile.profile != null) {
logger.i("We have a profile that needs to queued for broadcast: ${localProfile.profile}")
NavigationUIState.UnqueuedProfile(
profile = localProfile.profile
)
} else if (localProfile.nostrEvent != null) {
logger.i("Nostr event with the profile needs to be indexed: ${localProfile.nostrEvent}")
NavigationUIState.UnindexedProfile(
nostrEvent = localProfile.nostrEvent
)
} else if (localProfile.unsignedNostrEvent.signedAt != null && localProfile.synchronizeNostrEventRequests.isEmpty()) {
logger.i("We should request to sync profile: ${localProfile.unsignedNostrEvent}")
NavigationUIState.UnqueuedProfileSynchronization(
unsignedNostrEvent = localProfile.unsignedNostrEvent
)
} else if (localProfile.unsignedNostrEvent.signedAt != null && localProfile.synchronizeNostrEventRequests.isEmpty()) {
logger.i("We should be syncing the profile: ${localProfile.unsignedNostrEvent}")
NavigationUIState.UnsyncedProfile(
unsignedNostrEvent = localProfile.unsignedNostrEvent
)
} else {
logger.i("We have an unsigned profile: ${localProfile.unsignedNostrEvent}")
NavigationUIState.UnsignedProfile(
unsignedNostrEvent = localProfile.unsignedNostrEvent
)
}
}
}
}
private fun observeProfile() {
logger.i("observeProfile")
scope.launch(Dispatchers.IO) {
delay(2_100) // Looking busy...
delay(2_100.milliseconds) // Looking busy...
activeWalletStateFlow.collectLatest { activeWallet ->
logger.d("Active Wallet: $activeWallet")
if (activeWallet == null) {
_navigationUIState.getAndUpdate {
at.torch.compose.ui.view.state.NavigationUIState.StartupPhoenix
NavigationUIState.StartupPhoenix
}
} else {
if (activeWallet.business == null) {
_navigationUIState.getAndUpdate {
at.torch.compose.ui.view.state.NavigationUIState.StartupPhoenix
NavigationUIState.StartupPhoenix
}
} else {
val activeUserPublicKey = activeWallet.business.walletManager.keyManager.value?.nostrPublicKey()
if (activeUserPublicKey == null) {
_navigationUIState.getAndUpdate {
at.torch.compose.ui.view.state.NavigationUIState.Loading(text = "Couldn't get the nostrKey")
NavigationUIState.Loading(text = "Couldn't get the nostrKey")
}
} else {
logger.i("Observing: $activeUserPublicKey")
nostrRepository.observeProfile(
publicKey = activeUserPublicKey
).distinctUntilChanged().collect { localProfile ->
logger.i("Local Profile: $localProfile")
_navigationUIState.getAndUpdate {
if (localProfile == null) {
logger.i("We need to be on the landing screen so user creates account")
at.torch.compose.ui.view.state.NavigationUIState.Landing
} else if (localProfile.unsignedNostrEvent == null) {
logger.i("We need to be on the landing screen so user creates account")
at.torch.compose.ui.view.state.NavigationUIState.Landing
} else if (localProfile.broadcastNostrEventReceipt != null) {
logger.i("We have a broadcast receipt: ${localProfile.profile}")
at.torch.compose.ui.view.state.NavigationUIState.ProfileLoaded(
publicKey = localProfile.unsignedNostrEvent.pubKey
)
} else if (localProfile.unsignedNostrEvent.signedAt != null && localProfile.profile != null) {
logger.i("We have successfully synced a profile: ${localProfile.profile}")
at.torch.compose.ui.view.state.NavigationUIState.ProfileLoaded(
publicKey = localProfile.unsignedNostrEvent.pubKey
)
} else if (localProfile.broadcastNostrEventRequest != null) {
logger.i("We have a broadcast request: ${localProfile.broadcastNostrEventRequest}")
at.torch.compose.ui.view.state.NavigationUIState.UnannouncedProfile(
broadcastNostrEventRequest = localProfile.broadcastNostrEventRequest
)
} else if (localProfile.profile != null) {
logger.i("We have a profile that needs to queued for broadcast: ${localProfile.profile}")
at.torch.compose.ui.view.state.NavigationUIState.UnqueuedProfile(
profile = localProfile.profile
)
} else if (localProfile.nostrEvent != null) {
logger.i("Nostr event with the profile needs to be indexed: ${localProfile.nostrEvent}")
at.torch.compose.ui.view.state.NavigationUIState.UnindexedProfile(
nostrEvent = localProfile.nostrEvent
)
} else if (localProfile.unsignedNostrEvent.signedAt != null && localProfile.synchronizeNostrEventRequests.isEmpty()) {
logger.i("We should request to sync profile: ${localProfile.unsignedNostrEvent}")
at.torch.compose.ui.view.state.NavigationUIState.UnqueuedProfileSynchronization(
unsignedNostrEvent = localProfile.unsignedNostrEvent
)
} else if (localProfile.unsignedNostrEvent.signedAt != null && localProfile.synchronizeNostrEventRequests.isEmpty()) {
logger.i("We should be syncing the profile: ${localProfile.unsignedNostrEvent}")
at.torch.compose.ui.view.state.NavigationUIState.UnsyncedProfile(
unsignedNostrEvent = localProfile.unsignedNostrEvent
)
} else {
logger.i("We have an unsigned profile: ${localProfile.unsignedNostrEvent}")
at.torch.compose.ui.view.state.NavigationUIState.UnsignedProfile(
unsignedNostrEvent = localProfile.unsignedNostrEvent
)
}
}
}
loadNostrProfile(activeUserPublicKey)
}
}
logger.i("Navigation UI State is Landing")

View File

@@ -57,7 +57,7 @@ class SovereignWalletStartupViewModel(
)
when (startResult) {
is StartBusinessResult.Success -> {
state.value =StartupViewState.BusinessActive(walletId)
state.value = StartupViewState.BusinessActive(walletId)
launch(Dispatchers.Main) {
onStartupSuccess(startResult.business)
}

View File

@@ -95,6 +95,10 @@ class SovereignWalletViewModel(
publicKey = walletId.nodeIdHash,
balanceInSatoshis = 0 // TODO: Get balance...
)
viewModelScope.launch {
}
}