diff --git a/app/src/main/java/com/tangem/tap/data/DefaultCardSdkProvider.kt b/app/src/main/java/com/tangem/tap/data/DefaultCardSdkProvider.kt index 784db9dbc2..9918edc9f1 100644 --- a/app/src/main/java/com/tangem/tap/data/DefaultCardSdkProvider.kt +++ b/app/src/main/java/com/tangem/tap/data/DefaultCardSdkProvider.kt @@ -168,7 +168,7 @@ internal class DefaultCardSdkProvider @Inject constructor( secureStorage = secureStorage, authenticationManager = authenticationManager, keystoreManager = keystoreManager, - wordlist = Wordlist.getWordlist(activity), + wordlist = Wordlist.getWordlist(), config = config.apply { val apiConfig = apiConfigsManager.getEnvironmentConfig(id = ApiConfig.ID.TangemTech) tangemApiBaseUrl = apiConfig.baseUrl diff --git a/core/datasource/src/main/java/com/tangem/datasource/asset/loader/AssetLoader.kt b/core/datasource/src/main/java/com/tangem/datasource/asset/loader/AssetLoader.kt index 2bab1747cf..9325df9a70 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/asset/loader/AssetLoader.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/asset/loader/AssetLoader.kt @@ -3,10 +3,13 @@ package com.tangem.datasource.asset.loader import com.squareup.moshi.Moshi import com.squareup.moshi.Types import com.squareup.moshi.adapter -import com.tangem.utils.coroutines.runCatching +import com.tangem.core.analytics.api.AnalyticsExceptionHandler +import com.tangem.core.analytics.models.ExceptionAnalyticsEvent import com.tangem.datasource.asset.reader.AssetReader import com.tangem.datasource.di.NetworkMoshi import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.runCatching +import kotlinx.coroutines.withContext import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @@ -25,25 +28,44 @@ import javax.inject.Singleton class AssetLoader @Inject constructor( val assetReader: AssetReader, @NetworkMoshi val moshi: Moshi, + val analyticsExceptionHandler: AnalyticsExceptionHandler, val dispatchers: CoroutineDispatcherProvider, ) { /** Load content [Content] of asset file [fileName] */ + @Suppress("SuspendFunSwallowedCancellation") @OptIn(ExperimentalStdlibApi::class) - suspend inline fun load(fileName: String): Content? = runCatching(dispatchers.io) { - val json = assetReader.read(fullFileName = "$fileName.json") + suspend inline fun load(fileName: String): Content? = withContext(dispatchers.io) { + val json = runCatching { assetReader.read(fullFileName = "$fileName.json") }.getOrNull() - moshi.adapter().fromJson(json) + runCatching { + moshi.adapter().fromJson(json) + } + .fold( + onSuccess = { parsedConfig -> + if (parsedConfig == null) { + sendException( + fileName = fileName, + isParsingSuccess = true, + json = json, + ) + + Timber.e(IllegalStateException("Parsed config [$fileName] is null")) + } + + parsedConfig + }, + onFailure = { throwable -> + sendException( + fileName = fileName, + isParsingSuccess = false, + json = json, + ) + + Timber.e(throwable, "Failed to load config [$fileName] from assets") + null + }, + ) } - .fold( - onSuccess = { parsedConfig -> - if (parsedConfig == null) Timber.e(IllegalStateException("Parsed config [$fileName] is null")) - parsedConfig - }, - onFailure = { throwable -> - Timber.e(throwable, "Failed to load config [$fileName] from assets") - null - }, - ) /** Load list [V] values of asset file [fileName] */ suspend inline fun loadList(fileName: String): List = runCatching(dispatchers.io) { @@ -84,4 +106,18 @@ class AssetLoader @Inject constructor( emptyMap() }, ) + + fun sendException(fileName: String, isParsingSuccess: Boolean, json: String?) { + analyticsExceptionHandler.sendException( + ExceptionAnalyticsEvent( + exception = IllegalStateException("Parsing config is failed"), + params = mapOf( + "filename" to fileName, + "isParsingSuccess" to isParsingSuccess.toString(), + "json_size" to json?.length.toString(), + "json" to json?.take(n = 30).toString(), + ), + ), + ) + } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/asset/reader/AndroidAssetReader.kt b/core/datasource/src/main/java/com/tangem/datasource/asset/reader/AndroidAssetReader.kt index 3847d29980..b2c9c5b2e2 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/asset/reader/AndroidAssetReader.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/asset/reader/AndroidAssetReader.kt @@ -1,7 +1,6 @@ package com.tangem.datasource.asset.reader import android.content.res.AssetManager -import java.io.BufferedReader /** * Implementation of asset file reader @@ -13,7 +12,8 @@ internal class AndroidAssetReader( ) : AssetReader { override suspend fun read(fullFileName: String): String { - return assetManager.open(fullFileName).bufferedReader() - .use(BufferedReader::readText) + return assetManager.open(fullFileName, AssetManager.ACCESS_BUFFER).use { inputStream -> + inputStream.readBytes().toString(Charsets.UTF_8) + } } } \ No newline at end of file diff --git a/core/datasource/src/test/kotlin/com/tangem/datasource/asset/loader/AssetLoaderTest.kt b/core/datasource/src/test/kotlin/com/tangem/datasource/asset/loader/AssetLoaderTest.kt index 1bbee64573..a1594149d3 100644 --- a/core/datasource/src/test/kotlin/com/tangem/datasource/asset/loader/AssetLoaderTest.kt +++ b/core/datasource/src/test/kotlin/com/tangem/datasource/asset/loader/AssetLoaderTest.kt @@ -5,6 +5,7 @@ import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types import com.squareup.moshi.adapter +import com.tangem.core.analytics.api.AnalyticsExceptionHandler import com.tangem.datasource.api.express.models.response.Asset import com.tangem.datasource.asset.reader.AssetReader import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider @@ -23,9 +24,11 @@ class AssetLoaderTest { private val assetReader = mockk() private val moshi = mockk() + private val analyticsExceptionHandler = mockk() private val assetLoader = AssetLoader( assetReader = assetReader, moshi = moshi, + analyticsExceptionHandler = analyticsExceptionHandler, dispatchers = TestingCoroutineDispatcherProvider(), ) diff --git a/core/datasource/src/test/kotlin/com/tangem/datasource/asset/reader/AndroidAssetReaderTest.kt b/core/datasource/src/test/kotlin/com/tangem/datasource/asset/reader/AndroidAssetReaderTest.kt index 651d234c8d..93425e2814 100644 --- a/core/datasource/src/test/kotlin/com/tangem/datasource/asset/reader/AndroidAssetReaderTest.kt +++ b/core/datasource/src/test/kotlin/com/tangem/datasource/asset/reader/AndroidAssetReaderTest.kt @@ -18,7 +18,7 @@ internal class AndroidAssetReaderTest { @Test fun read_content() = runTest { - every { assetManager.open(FILE_NAME) } returns json.byteInputStream() + every { assetManager.open(FILE_NAME, AssetManager.ACCESS_BUFFER) } returns json.byteInputStream() val actual = assetReader.read(fullFileName = FILE_NAME) @@ -28,7 +28,7 @@ internal class AndroidAssetReaderTest { @Test fun read_error() = runTest { val exception = IOException("Error") - every { assetManager.open(FILE_NAME) } throws exception + every { assetManager.open(FILE_NAME, AssetManager.ACCESS_BUFFER) } throws exception runCatching { assetReader.read(fullFileName = FILE_NAME) } .onSuccess { throw IllegalStateException("Error should be thrown") } diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/common/repository/DefaultMnemonicRepository.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/common/repository/DefaultMnemonicRepository.kt index 0c3b768d31..921f2d9db3 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/common/repository/DefaultMnemonicRepository.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/common/repository/DefaultMnemonicRepository.kt @@ -1,6 +1,5 @@ package com.tangem.features.hotwallet.common.repository -import android.content.Context import com.tangem.crypto.bip39.DefaultMnemonic import com.tangem.crypto.bip39.EntropyLength import com.tangem.crypto.bip39.Mnemonic @@ -8,15 +7,13 @@ import com.tangem.crypto.bip39.Wordlist import com.tangem.features.hotwallet.MnemonicRepository import com.tangem.features.hotwallet.MnemonicRepository.MnemonicType import com.tangem.sdk.extensions.getWordlist -import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject -internal class DefaultMnemonicRepository @Inject constructor( - @ApplicationContext private val context: Context, -) : MnemonicRepository { - private val wordlist = Wordlist.getWordlist(context) +internal class DefaultMnemonicRepository @Inject constructor() : MnemonicRepository { - override val words: Set = wordlist.words.toHashSet() + private val wordlist by lazy(LazyThreadSafetyMode.NONE) { Wordlist.getWordlist() } + + override val words: Set by lazy(LazyThreadSafetyMode.NONE) { wordlist.words.toHashSet() } override fun generateMnemonic(type: MnemonicType): Mnemonic = DefaultMnemonic( entropy = when (type) { diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 4d426f621c..b6a00beda3 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -7,11 +7,11 @@ tangemBlockchainSdk = "releases-5.35-1449" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "releases-5.35-589" +tangemCardSdk = "releases-5.35-593" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem12" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ -tangemHotSdk = "develop-539" +tangemHotSdk = "develop-547" #tangemHotSdk = "0.0.1" # Keep it! - used for local builds ^