Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-09 15:03:19 +05:00
parent ea780f563e
commit 42c8be234e
18 changed files with 275 additions and 193 deletions

View file

@ -1,6 +1,9 @@
package com.tangem.tap
import android.app.Application
import android.os.StrictMode
import android.os.StrictMode.ThreadPolicy
import android.os.StrictMode.VmPolicy
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
import coil.ImageLoader
@ -71,9 +74,7 @@ import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.wallet.BuildConfig
import dagger.hilt.EntryPoints
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.*
import org.rekotlin.Store
import kotlin.collections.set
import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository as WalletConnect2Repository
@ -228,12 +229,32 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat
// endregion
private val appScope = MainScope()
override fun onCreate() {
enableStrictModeInDebug()
super.onCreate()
init()
}
updateLogFiles()
private fun enableStrictModeInDebug() {
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(
ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectAll()
.penaltyLog()
.build(),
)
StrictMode.setVmPolicy(
VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.build(),
)
}
}
private fun updateLogFiles() {
@ -260,18 +281,31 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat
foregroundActivityObserver = ForegroundActivityObserver()
registerActivityLifecycleCallbacks(foregroundActivityObserver.callbacks)
// TODO: Try to performance and user experience.
// [REDACTED_JIRA]
// We need to initialize the toggles and excludedBlockchainsManager before the MainActivity starts using them.
runBlocking {
awaitAll(
async { featureTogglesManager.init() },
async { excludedBlockchainsManager.init() },
async { initWithConfigDependency(environmentConfig = environmentConfigStorage.initialize()) },
async {
featureTogglesManager.init()
},
async {
excludedBlockchainsManager.init()
},
)
}
loadNativeLibraries()
appScope.launch {
initWithConfigDependency(environmentConfig = environmentConfigStorage.initialize())
launch(Dispatchers.IO) {
loadNativeLibraries()
walletConnect2Repository.init(
projectId = environmentConfigStorage.getConfigSync().walletConnectProjectId,
)
updateLogFiles()
}
}
ExceptionHandler.append(blockchainExceptionHandler)
if (LogConfig.network.blockchainSdkNetwork) {
BlockchainSdkRetrofitBuilder.interceptors = listOf(
createNetworkLoggingInterceptor(),
@ -287,9 +321,8 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat
appPreferencesStore = appPreferencesStore,
dispatchers = dispatchers,
)
appStateHolder.mainStore = store
walletConnect2Repository.init(projectId = environmentConfigStorage.getConfigSync().walletConnectProjectId)
appStateHolder.mainStore = store
}
private fun createReduxStore(): Store<AppState> {

View file

@ -20,18 +20,22 @@ internal class DefaultVisaAuthTokenStorage @Inject constructor(
private val dispatcherProvider: CoroutineDispatcherProvider,
) : VisaAuthTokenStorage {
private val secureStorage = AndroidSecureStorage(
preferences = SecureStorage.createEncryptedSharedPreferences(
context = applicationContext,
storageName = "visa_auth_storage",
),
)
private val secureStorage by lazy {
AndroidSecureStorage(
preferences = SecureStorage.createEncryptedSharedPreferences(
context = applicationContext,
storageName = "visa_auth_storage",
),
)
}
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
private val moshi by lazy {
Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
}
private val tokensAdapter = moshi.adapter(VisaAuthTokens::class.java)
private val tokensAdapter by lazy { moshi.adapter(VisaAuthTokens::class.java) }
override suspend fun store(cardId: String, tokens: VisaAuthTokens) = withContext(dispatcherProvider.io) {
val json = tokensAdapter.toJson(tokens)

View file

@ -20,12 +20,14 @@ class DefaultVisaOTPStorage @Inject constructor(
private val dispatcherProvider: CoroutineDispatcherProvider,
) : VisaOTPStorage {
private val secureStorage = AndroidSecureStorage(
preferences = SecureStorage.createEncryptedSharedPreferences(
context = applicationContext,
storageName = "visa_otp_storage",
),
)
private val secureStorage by lazy {
AndroidSecureStorage(
preferences = SecureStorage.createEncryptedSharedPreferences(
context = applicationContext,
storageName = "visa_otp_storage",
),
)
}
override suspend fun saveOTP(cardId: String, data: VisaOtpData) = withContext(dispatcherProvider.io) {
secureStorage.store(data.rootOTP, VISA_ROOT_OTP_KEY_PREFIX + cardId)

View file

@ -20,9 +20,12 @@ internal class DefaultUserWalletsPublicInformationRepository(
moshi: Moshi,
private val secureStorage: SecureStorage,
) : UserWalletsPublicInformationRepository {
private val publicInformationAdapter: JsonAdapter<List<UserWalletPublicInformation>> = moshi.adapter(
Types.newParameterizedType(List::class.java, UserWalletPublicInformation::class.java),
)
private val publicInformationAdapter: JsonAdapter<List<UserWalletPublicInformation>> by lazy {
moshi.adapter(
Types.newParameterizedType(List::class.java, UserWalletPublicInformation::class.java),
)
}
override suspend fun save(userWallet: UserWallet, canOverride: Boolean): CompletionResult<Unit> {
return withContext(Dispatchers.IO) {

View file

@ -24,12 +24,15 @@ internal class DefaultUserWalletsSensitiveInformationRepository(
private val secureStorage: SecureStorage,
) : UserWalletsSensitiveInformationRepository {
private val sensitiveInformationAdapter: JsonAdapter<UserWalletSensitiveInformation> = moshi.adapter(
UserWalletSensitiveInformation::class.java,
)
private val encryptedSensitiveInformationMapAdapter: JsonAdapter<Map<String, ByteArray>> = moshi.adapter(
Types.newParameterizedType(Map::class.java, String::class.java, ByteArray::class.java),
)
private val sensitiveInformationAdapter: JsonAdapter<UserWalletSensitiveInformation> by lazy {
moshi.adapter(UserWalletSensitiveInformation::class.java)
}
private val encryptedSensitiveInformationMapAdapter: JsonAdapter<Map<String, ByteArray>> by lazy {
moshi.adapter(
Types.newParameterizedType(Map::class.java, String::class.java, ByteArray::class.java),
)
}
override suspend fun save(userWallet: UserWallet, encryptionKey: ByteArray?): CompletionResult<Unit> {
if (encryptionKey == null) {