Skip to content

Commit

Permalink
Complete refactor of SeedVaultSimulator to use Hilt dependency inject…
Browse files Browse the repository at this point in the history
…ion (#376)
  • Loading branch information
sdlaver authored Dec 4, 2024
1 parent 8d631f2 commit 5c3a3d7
Show file tree
Hide file tree
Showing 15 changed files with 162 additions and 163 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,7 @@
package com.solanamobile.seedvaultimpl

import android.app.Application
import com.solanamobile.seedvaultimpl.data.SeedRepository
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import javax.inject.Inject

@HiltAndroidApp
class SeedVaultImplApplication : Application() {
@Inject
lateinit var seedRepository: SeedRepository

// TODO: remove dependencyContainer in favor of hilt/dagger injection
val dependencyContainer: ApplicationDependencyContainer by lazy {
ApplicationDependencyContainer(seedRepository)
}
}
class SeedVaultImplApplication : Application()
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2024 Solana Mobile Inc.
*/

package com.solanamobile.seedvaultimpl

import com.goterl.lazysodium.LazySodiumAndroid
import com.goterl.lazysodium.SodiumAndroid
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import java.nio.charset.StandardCharsets

@Module
@InstallIn(SingletonComponent::class)
class SodiumAndroidProvider {
@Provides
fun provideLazySodiumAndroid() : LazySodiumAndroid {
return LazySodiumAndroid(SodiumAndroid(), StandardCharsets.UTF_8)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,30 @@ import android.util.Log
import com.solanamobile.seedvault.BipDerivationPath
import com.solanamobile.seedvault.WalletContractV1
import com.solanamobile.seedvault.WalletContractV1.AUTHORITY_WALLET_PROVIDER
import com.solanamobile.seedvaultimpl.ApplicationDependencyContainer
import com.solanamobile.seedvaultimpl.SeedVaultImplApplication
import com.solanamobile.seedvaultimpl.data.SeedRepository
import com.solanamobile.seedvaultimpl.model.Authorization
import com.solanamobile.seedvaultimpl.usecase.Base58EncodeUseCase
import com.solanamobile.seedvaultimpl.usecase.RequestLimitsUseCase
import com.solanamobile.seedvaultimpl.usecase.normalize
import com.solanamobile.seedvaultimpl.usecase.toBip32DerivationPath
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

class WalletContentProvider : ContentProvider() {
private lateinit var dependencyContainer: ApplicationDependencyContainer
@EntryPoint
@InstallIn(SingletonComponent::class)
interface WalletContentProviderHiltEntryPoint {
fun provideSeedRepository(): SeedRepository
}

private lateinit var seedRepository: SeedRepository

override fun onCreate(): Boolean {
// NOTE: this occurs before the Application instance is created, so we can't do our
Expand Down Expand Up @@ -91,7 +99,6 @@ class WalletContentProvider : ContentProvider() {

// NOTE: A real Seed Vault implementation should NOT provide this method
private fun callResetSeedVaultSimulator(): Bundle? {
val seedRepository = dependencyContainer.seedRepository
runBlocking {
seedRepository.delayUntilDataValid()
seedRepository.deleteAllSeeds()
Expand Down Expand Up @@ -185,7 +192,6 @@ class WalletContentProvider : ContentProvider() {
val filteredProjection = projection?.intersect(defaultProjection) ?: defaultProjection
val cursor = MatrixCursor(filteredProjection.toTypedArray())

val seedRepository = dependencyContainer.seedRepository
runBlocking {
seedRepository.delayUntilDataValid()

Expand Down Expand Up @@ -235,7 +241,6 @@ class WalletContentProvider : ContentProvider() {
val filteredProjection = projection?.intersect(defaultProjection) ?: defaultProjection
val cursor = MatrixCursor(filteredProjection.toTypedArray())

val seedRepository = dependencyContainer.seedRepository
runBlocking {
seedRepository.delayUntilDataValid()
if (callerIsPrivileged) {
Expand Down Expand Up @@ -290,7 +295,6 @@ class WalletContentProvider : ContentProvider() {
val filteredProjection = projection?.intersect(defaultProjection) ?: defaultProjection
val cursor = MatrixCursor(filteredProjection.toTypedArray())

val seedRepository = dependencyContainer.seedRepository
runBlocking {
seedRepository.delayUntilDataValid()
}
Expand Down Expand Up @@ -405,7 +409,6 @@ class WalletContentProvider : ContentProvider() {
uid: Int,
@WalletContractV1.AuthToken authToken: Long
): Int {
val seedRepository = dependencyContainer.seedRepository
runBlocking {
seedRepository.delayUntilDataValid()
}
Expand Down Expand Up @@ -464,7 +467,6 @@ class WalletContentProvider : ContentProvider() {
@WalletContractV1.AccountId accountId: Long,
values: ContentValues?
): Int {
val seedRepository = dependencyContainer.seedRepository
runBlocking {
seedRepository.delayUntilDataValid()
}
Expand Down Expand Up @@ -512,12 +514,11 @@ class WalletContentProvider : ContentProvider() {
private fun checkDependencyInjection() {
// Note: this can be executed in an arbitrary thread context. Use double-checked locking
// pattern to safely initialize it.
if (!this::dependencyContainer.isInitialized) {
val didInitialization = synchronized(this::dependencyContainer) {
if (!this::dependencyContainer.isInitialized) {
dependencyContainer =
(requireContext().applicationContext as SeedVaultImplApplication)
.dependencyContainer
if (!this::seedRepository.isInitialized) {
val didInitialization = synchronized(this::seedRepository) {
if (!this::seedRepository.isInitialized) {
val hiltEntryPoint = EntryPointAccessors.fromApplication(requireContext().applicationContext, WalletContentProviderHiltEntryPoint::class.java)
seedRepository = hiltEntryPoint.provideSeedRepository()
true
} else {
false
Expand All @@ -533,7 +534,7 @@ class WalletContentProvider : ContentProvider() {
private fun observeSeedRepositoryChanges() {
val repositoryOwnerScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
repositoryOwnerScope.launch {
dependencyContainer.seedRepository.changes.collect { change ->
seedRepository.changes.collect { change ->
// NOTE: this is overeager; we aren't checking, e.g., if deleting a particular seed
// will affect an observer watching a particular account.
val uris: List<Uri> = when (change.category) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ class SeedRepository @Inject constructor(

@WalletContractV1.AccountId
suspend fun addKnownAccountForSeed(id: Long, account: Account): Long {
require(account.id == Account.INVALID_ACCOUNT_ID) { "Accound ID must be invalid" }
require(account.id == Account.INVALID_ACCOUNT_ID) { "Account ID must be invalid" }
Log.d(TAG, "ENTER addKnownAccountForSeed")

@WalletContractV1.AccountId val accountId: Long
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,29 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.solanamobile.seedvault.WalletContractV1
import com.solanamobile.seedvaultimpl.SeedVaultImplApplication
import com.solanamobile.seedvaultimpl.ui.authorize.AuthorizeContents
import com.solanamobile.seedvaultimpl.ui.authorize.AuthorizeViewModel
import com.solanamobile.seedvaultimpl.ui.authorizeinfo.AuthorizeInfoContents
import com.solanamobile.seedvaultimpl.ui.selectseed.SelectSeedContents
import com.solanamobile.seedvaultimpl.ui.selectseed.SelectSeedViewModel
import com.solanamobile.ui.apptheme.SolanaTheme
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.withCreationCallback
import kotlinx.coroutines.launch

@AndroidEntryPoint
class AuthorizeActivity : ComponentActivity() {
private val activityViewModel: AuthorizeViewModel by viewModels()
private val authorizeViewModel: com.solanamobile.seedvaultimpl.ui.authorize.AuthorizeViewModel by viewModels {
com.solanamobile.seedvaultimpl.ui.authorize.AuthorizeViewModel.provideFactory(
(application as SeedVaultImplApplication).dependencyContainer.seedRepository,
activityViewModel,
application
)
}
private val selectSeedViewModel: SelectSeedViewModel by viewModels {
SelectSeedViewModel.provideFactory(
(application as SeedVaultImplApplication).dependencyContainer.seedRepository,
activityViewModel
)
}
private val authorizeCommonViewModel: AuthorizeCommonViewModel by viewModels()
private val authorizeViewModel: AuthorizeViewModel by viewModels(extrasProducer = {
defaultViewModelCreationExtras.withCreationCallback<AuthorizeViewModel.Factory> { factory ->
factory.create(authorizeCommonViewModel)
}
})
private val selectSeedViewModel: SelectSeedViewModel by viewModels(extrasProducer = {
defaultViewModelCreationExtras.withCreationCallback<SelectSeedViewModel.Factory> { factory ->
factory.create(authorizeCommonViewModel)
}
})

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down Expand Up @@ -106,7 +106,7 @@ class AuthorizeActivity : ComponentActivity() {
navController.navigateUp()
},
completeAuthorizationWithError = {
activityViewModel.completeAuthorizationWithError(
authorizeCommonViewModel.completeAuthorizationWithError(
WalletContractV1.RESULT_UNSPECIFIED_ERROR
)
},
Expand Down Expand Up @@ -134,10 +134,10 @@ class AuthorizeActivity : ComponentActivity() {
null
}

activityViewModel.setRequest(callingActivity, uid, intent)
authorizeCommonViewModel.setRequest(callingActivity, uid, intent)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
activityViewModel.events.collect { event ->
authorizeCommonViewModel.events.collect { event ->
when (event.event) {
AuthorizeEventType.COMPLETE -> {
Log.i(TAG, "Returning result=${event.resultCode}/intent=${event.data} from AuthorizeActivity")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch

@HiltViewModel
class AuthorizeViewModel @Inject constructor() : ViewModel() {
class AuthorizeCommonViewModel @Inject constructor() : ViewModel() {
private val _requests = MutableSharedFlow<AuthorizeRequest>(replay = 1)
val requests = _requests.asSharedFlow()

Expand Down Expand Up @@ -187,7 +187,7 @@ class AuthorizeViewModel @Inject constructor() : ViewModel() {
}

companion object {
private val TAG = AuthorizeViewModel::class.simpleName
private val TAG = AuthorizeCommonViewModel::class.simpleName
}
}

Expand Down
Loading

0 comments on commit 5c3a3d7

Please sign in to comment.