From 07f94d3a9554862ab740ec965f403609d46d1c38 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 12 Mar 2026 17:55:33 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../AppsFlyerReferralParamsHandler.kt | 7 +-- .../appsflyer/AppsFlyerAnalyticsClient.kt | 8 +--- .../tap/core/DefaultAppCoroutineScope.kt | 44 +++++++++++++++++ .../java/com/tangem/tap/di/ActivityModule.kt | 7 ++- .../tangem/tap/di/TangemSdkManagerModule.kt | 6 +-- .../java/com/tangem/tap/di/UtilsModule.kt | 36 +++++++++----- .../tap/di/domain/TransactionDomainModule.kt | 8 ++-- .../tap/di/domain/YieldSupplyDomainModule.kt | 7 ++- .../sdk/impl/DefaultTangemSdkManager.kt | 6 +-- .../AppsFlyerReferralParamsHandlerTest.kt | 4 +- .../common/test/TestAppCoroutineScope.kt | 11 +++++ .../core/abtests/di/ABTestsManagerModule.kt | 8 ++-- .../manager/impl/AmplitudeABTestsManager.kt | 4 +- .../config/managers/DevApiConfigsManager.kt | 8 ++-- .../config/managers/MockApiConfigsManager.kt | 22 ++++++--- .../di/AppPreferencesStoreModule.kt | 4 +- .../datasource/di/ExpressAssetsStoreModule.kt | 8 ++-- .../com/tangem/datasource/di/NetworkModule.kt | 8 ++-- .../datasource/di/StakingStoreModule.kt | 20 ++++---- .../di/TokenReceiveWarningModule.kt | 8 ++-- .../datasource/di/WalletConnectModule.kt | 7 +-- .../tangem/datasource/di/YieldSupplyModule.kt | 8 ++-- .../datasource/local/logs/AppLogsStore.kt | 7 +-- .../local/nft/NFTPersistenceStoreFactory.kt | 8 ++-- .../local/preferences/PreferencesDataStore.kt | 12 ++--- .../utils/coroutines/AppCoroutineScope.kt | 5 ++ .../tangem/utils/coroutines/DelayedWork.kt | 7 --- .../utils/di/DelayedWorkCoroutineModule.kt | 23 --------- .../data/account/di/AccountDataModule.kt | 11 ++--- .../store/AccountsResponseStoreFactory.kt | 8 ++-- .../DefaultMainAccountTokensMigration.kt | 8 +--- .../store/AccountsResponseStoreFactoryTest.kt | 4 +- .../DefaultMainAccountTokensMigrationTest.kt | 4 +- .../tangem/data/common/di/DataCommonModule.kt | 6 +-- .../common/quote/DefaultQuotesFetcherTest.kt | 6 +-- .../data/networks/di/NetworkDataModule.kt | 9 ++-- .../store/DefaultNetworksStatusesStore.kt | 6 +-- .../com/tangem/data/networks/store/GetTest.kt | 4 +- .../data/networks/store/InitializationTest.kt | 8 ++-- .../store/ParameterizedStoreStatusTest.kt | 4 +- .../store/ParameterizedStoreSuccessTest.kt | 4 +- .../networks/store/ParameterizedStoreTest.kt | 4 +- .../networks/store/SetSourceAsCacheTest.kt | 4 +- .../store/SetSourceAsOnlyCacheTest.kt | 4 +- .../data/networks/store/StoreStatusTest.kt | 4 +- .../data/networks/store/StoreSuccessTest.kt | 4 +- .../tangem/data/networks/store/StoreTest.kt | 4 +- .../networks/store/UpdateStatusSourceTest.kt | 4 +- .../data/onramp/DefaultHotCryptoRepository.kt | 7 +-- .../tangem/data/onramp/di/OnrampDataModule.kt | 3 ++ .../tangem/data/quotes/di/QuotesDataModule.kt | 14 +++--- .../quotes/multi/DefaultMultiQuoteUpdater.kt | 7 +-- .../store/DefaultQuotesStatusesStore.kt | 8 +--- .../DefaultMultiQuoteStatusUpdaterTest.kt | 4 +- .../store/QuotesStatusesStoreExtTest.kt | 4 +- .../quotes/store/QuotesStatusesStoreTest.kt | 10 ++-- .../di/StakingBalanceSupplierModule.kt | 10 ++-- .../store/DefaultP2PEthPoolBalancesStore.kt | 8 +--- .../store/DefaultStakeKitBalancesStore.kt | 8 +--- .../StakingBalancesStoreGetMethodTest.kt | 4 +- .../StakingBalancesStoreInitializationTest.kt | 8 ++-- .../StakingBalancesStoreUpdateMethodsTest.kt | 4 +- .../pay/DefaultTangemPayEligibilityManager.kt | 5 +- .../tangem/data/pay/di/TangemPayDataModule.kt | 8 ++-- .../DefaultTangemPayCardDetailsRepository.kt | 3 +- .../DefaultTangemPayWithdrawRepository.kt | 3 +- .../pay/store/PaymentAccountStatusesStore.kt | 8 +--- .../di/WalletConnectDataModule.kt | 14 ++---- .../walletconnect/pair/WcPairSdkDelegate.kt | 4 +- .../sessions/DefaultWcSessionsManager.kt | 3 +- .../data/walletconnect/utils/WcScope.kt | 13 ----- .../wallets/hot/DefaultHotWalletAccessor.kt | 8 +--- domain/account/status/build.gradle.kts | 1 + .../AccountStatusListProducerFactoryModule.kt | 5 -- .../status/di/AccountStatusUseCaseModule.kt | 10 ++-- .../producer/DefaultFlowProducerTools.kt | 48 +++---------------- .../usecase/ManageCryptoCurrenciesUseCase.kt | 3 +- .../tangem/domain/core/flow/FlowProducer.kt | 3 -- .../usecase/SendTransactionUseCase.kt | 4 +- .../usecase/YieldSupplyPendingTracker.kt | 4 +- .../usecase/YieldSupplyPendingTrackerTest.kt | 3 +- .../send/v2/common/SendBalanceUpdater.kt | 11 +++-- .../impl/presentation/model/StakingModel.kt | 4 +- .../state/helpers/StakingBalanceUpdater.kt | 4 +- .../utils/AccountListSortingSaver.kt | 8 +--- .../di/BlockchainSDKFactoryModule.kt | 7 ++- 86 files changed, 317 insertions(+), 387 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/core/DefaultAppCoroutineScope.kt create mode 100644 common/test/src/main/java/com/tangem/common/test/TestAppCoroutineScope.kt create mode 100644 core/utils/src/main/java/com/tangem/utils/coroutines/AppCoroutineScope.kt delete mode 100644 core/utils/src/main/java/com/tangem/utils/coroutines/DelayedWork.kt delete mode 100644 core/utils/src/main/java/com/tangem/utils/di/DelayedWorkCoroutineModule.kt delete mode 100644 data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcScope.kt diff --git a/app/src/main/java/com/tangem/tap/common/analytics/appsflyer/AppsFlyerReferralParamsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/appsflyer/AppsFlyerReferralParamsHandler.kt index cd9e78634b..a643b0142e 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/appsflyer/AppsFlyerReferralParamsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/appsflyer/AppsFlyerReferralParamsHandler.kt @@ -2,11 +2,9 @@ package com.tangem.tap.common.analytics.appsflyer import com.appsflyer.deeplink.DeepLink import com.tangem.datasource.local.appsflyer.AppsFlyerStore +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.wallets.models.AppsFlyerConversionData import com.tangem.feature.referral.domain.SetShouldShowMobileWalletPromoUseCase -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock @@ -20,10 +18,9 @@ import kotlin.contracts.contract class AppsFlyerReferralParamsHandler @Inject constructor( private val appsFlyerStore: AppsFlyerStore, private val setShouldShowMobileWalletPromoUseCase: SetShouldShowMobileWalletPromoUseCase, - dispatchers: CoroutineDispatcherProvider, + private val coroutineScope: AppCoroutineScope, ) { - private val coroutineScope = CoroutineScope(dispatchers.io + SupervisorJob()) private val mutex = Mutex() fun handle(deepLink: DeepLink) { diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsClient.kt index f5aa24257d..2f07e571b1 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsClient.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsClient.kt @@ -6,16 +6,14 @@ import com.appsflyer.attribution.AppsFlyerRequestListener import com.tangem.core.analytics.api.EventLogger import com.tangem.core.analytics.api.UserIdHolder import com.tangem.datasource.local.appsflyer.AppsFlyerStore +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.tap.common.analytics.appsflyer.AppsFlyerDeepLinkListener import com.tangem.tap.common.analytics.appsflyer.TangemAFConversionListener import com.tangem.tap.common.analytics.handlers.firebase.UnderscoreAnalyticsEventConverter -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import timber.log.Timber @@ -26,15 +24,13 @@ class AppsFlyerClient @AssistedInject constructor( @ApplicationContext private val context: Context, appsFlyerDeepLinkListener: AppsFlyerDeepLinkListener, tangemAFConversionListener: TangemAFConversionListener, - dispatchers: CoroutineDispatcherProvider, private val appsFlyerStore: AppsFlyerStore, + private val coroutineScope: AppCoroutineScope, ) : AppsFlyerAnalyticsClient { private val appsFlyerLib: AppsFlyerLib = AppsFlyerLib.getInstance() private val eventConverter = UnderscoreAnalyticsEventConverter() - private val coroutineScope = CoroutineScope(SupervisorJob() + dispatchers.default) - init { with(appsFlyerLib) { setAppId(context.packageName) diff --git a/app/src/main/java/com/tangem/tap/core/DefaultAppCoroutineScope.kt b/app/src/main/java/com/tangem/tap/core/DefaultAppCoroutineScope.kt new file mode 100644 index 0000000000..190af9d4eb --- /dev/null +++ b/app/src/main/java/com/tangem/tap/core/DefaultAppCoroutineScope.kt @@ -0,0 +1,44 @@ +package com.tangem.tap.core + +import co.touchlab.kermit.Logger +import com.tangem.core.analytics.api.AnalyticsExceptionHandler +import com.tangem.core.analytics.models.ExceptionAnalyticsEvent +import com.tangem.utils.coroutines.AppCoroutineScope +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.SupervisorJob +import javax.inject.Inject +import kotlin.coroutines.CoroutineContext + +internal class DefaultAppCoroutineScope @Inject constructor( + dispatchers: CoroutineDispatcherProvider, + private val analyticsExceptionHandler: AnalyticsExceptionHandler, +) : AppCoroutineScope { + + private val tag = "AppCoroutineScope" + + override val coroutineContext: CoroutineContext = SupervisorJob() + + // keep IO dispatcher to avoid blocking Default with IO operations + dispatchers.io + + CoroutineName(tag) + + CoroutineExceptionHandler { context, throwable -> + val coroutineName = context[CoroutineName]?.name.orEmpty() + logError(throwable, coroutineName) + } + + private fun logError(throwable: Throwable, coroutineName: String) { + Logger.withTag(tag).e( + messageString = "CoroutineName $coroutineName", + throwable = throwable, + ) + val event = ExceptionAnalyticsEvent( + exception = throwable, + params = mapOf( + "source" to tag, + "coroutineName" to coroutineName, + ), + ) + analyticsExceptionHandler.sendException(event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/di/ActivityModule.kt b/app/src/main/java/com/tangem/tap/di/ActivityModule.kt index e5600cc208..e3e54d1699 100644 --- a/app/src/main/java/com/tangem/tap/di/ActivityModule.kt +++ b/app/src/main/java/com/tangem/tap/di/ActivityModule.kt @@ -4,6 +4,7 @@ import com.tangem.datasource.api.moonpay.MoonPayApi import com.tangem.datasource.local.config.environment.EnvironmentConfig import com.tangem.domain.card.ScanCardUseCase import com.tangem.domain.card.repository.CardSdkConfigRepository +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.exchange.RampStateManager import com.tangem.domain.express.ExpressServiceFetcher import com.tangem.domain.tokens.repository.CurrenciesRepository @@ -21,8 +22,6 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -62,8 +61,8 @@ internal object ActivityModule { @Provides @Singleton @DelayedWork - fun provideActivityDelayedWorkCoroutineScope(): CoroutineScope { - return CoroutineScope(SupervisorJob() + Dispatchers.IO) + fun provideActivityDelayedWorkCoroutineScope(appScope: AppCoroutineScope): CoroutineScope { + return appScope } @Provides diff --git a/app/src/main/java/com/tangem/tap/di/TangemSdkManagerModule.kt b/app/src/main/java/com/tangem/tap/di/TangemSdkManagerModule.kt index 53f53dffef..8febdb45f1 100644 --- a/app/src/main/java/com/tangem/tap/di/TangemSdkManagerModule.kt +++ b/app/src/main/java/com/tangem/tap/di/TangemSdkManagerModule.kt @@ -8,6 +8,7 @@ import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.navigation.finisher.AppFinisher import com.tangem.domain.card.BuildConfig import com.tangem.domain.card.repository.CardSdkConfigRepository +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles import com.tangem.sdk.api.TangemSdkManager @@ -17,7 +18,6 @@ import com.tangem.tap.domain.tasks.product.BlockchainToDeriveFinder import com.tangem.tap.domain.tasks.visa.TangemPayGenerateAddressAndSignChallengeTask import com.tangem.tap.domain.tasks.visa.VisaCardActivationTask import com.tangem.tap.domain.visa.VisaCardScanHandler -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -44,7 +44,7 @@ internal class TangemSdkManagerModule { analyticsExceptionHandler: AnalyticsExceptionHandler, blockchainToDeriveFinder: BlockchainToDeriveFinder, analyticsEventHandler: AnalyticsEventHandler, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): TangemSdkManager { return if (BuildConfig.MOCK_DATA_SOURCE) { MockTangemSdkManager(resources = context.resources) @@ -62,7 +62,7 @@ internal class TangemSdkManagerModule { analyticsExceptionHandler = analyticsExceptionHandler, blockchainToDeriveFinder = blockchainToDeriveFinder, analyticsEventHandler = analyticsEventHandler, - dispatchers = dispatchers, + coroutineScope = appScope, ) } } diff --git a/app/src/main/java/com/tangem/tap/di/UtilsModule.kt b/app/src/main/java/com/tangem/tap/di/UtilsModule.kt index 7fdf0263cc..8ee75b9d1a 100644 --- a/app/src/main/java/com/tangem/tap/di/UtilsModule.kt +++ b/app/src/main/java/com/tangem/tap/di/UtilsModule.kt @@ -5,10 +5,13 @@ import com.tangem.core.navigation.finisher.AppFinisher import com.tangem.core.navigation.settings.SettingsManager import com.tangem.core.navigation.share.ShareManager import com.tangem.core.navigation.url.UrlOpener +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.tap.common.finisher.AndroidAppFinisher import com.tangem.tap.common.settings.IntentSettingsManager import com.tangem.tap.common.share.IntentShareManager import com.tangem.tap.common.url.CustomTabsUrlOpener +import com.tangem.tap.core.DefaultAppCoroutineScope +import dagger.Binds import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -18,21 +21,28 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) -internal object UtilsModule { +internal interface UtilsModule { - @Provides - @Singleton - fun provideShareManager(): ShareManager = IntentShareManager() + @Binds + fun provideAppScope(defaultAppScope: DefaultAppCoroutineScope): AppCoroutineScope - @Provides - @Singleton - fun provideUrlOpener(): UrlOpener = CustomTabsUrlOpener() + companion object { - @Provides - @Singleton - fun provideAppFinisher(@ApplicationContext context: Context): AppFinisher = AndroidAppFinisher(context) + @Provides + @Singleton + fun provideShareManager(): ShareManager = IntentShareManager() - @Provides - @Singleton - fun provideSettingsManager(@ApplicationContext context: Context): SettingsManager = IntentSettingsManager(context) + @Provides + @Singleton + fun provideUrlOpener(): UrlOpener = CustomTabsUrlOpener() + + @Provides + @Singleton + fun provideAppFinisher(@ApplicationContext context: Context): AppFinisher = AndroidAppFinisher(context) + + @Provides + @Singleton + fun provideSettingsManager(@ApplicationContext context: Context): SettingsManager = + IntentSettingsManager(context) + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt index 16a63b51aa..cfeacf9297 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt @@ -4,6 +4,7 @@ import com.tangem.data.wallets.hot.TangemHotWalletSigner import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.card.repository.CardSdkConfigRepository +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.demo.models.DemoConfig import com.tangem.domain.networks.single.SingleNetworkStatusFetcher import com.tangem.domain.networks.single.SingleNetworkStatusSupplier @@ -18,13 +19,10 @@ import com.tangem.domain.transaction.WalletAddressServiceRepository import com.tangem.domain.transaction.usecase.* import com.tangem.domain.transaction.usecase.gasless.* import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Suppress("TooManyFunctions", "LargeClass") @@ -55,8 +53,8 @@ internal object TransactionDomainModule { walletManagersFacade: WalletManagersFacade, singleNetworkStatusFetcher: SingleNetworkStatusFetcher, tangemHotWalletSignerFactory: TangemHotWalletSigner.Factory, - dispatchers: CoroutineDispatcherProvider, pushNotificationsRepository: PushNotificationsRepository, + appScope: AppCoroutineScope, ): SendTransactionUseCase { return SendTransactionUseCase( demoConfig = DemoConfig, @@ -64,7 +62,7 @@ internal object TransactionDomainModule { transactionRepository = transactionRepository, walletManagersFacade = walletManagersFacade, singleNetworkStatusFetcher = singleNetworkStatusFetcher, - parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.io), + parallelUpdatingScope = appScope, getHotWalletSigner = tangemHotWalletSignerFactory::create, pushNotificationsRepository = pushNotificationsRepository, ) diff --git a/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt index c893ae8a08..fbc69fcf80 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt @@ -1,6 +1,7 @@ package com.tangem.tap.di.domain import com.tangem.domain.blockaid.BlockAidGasEstimate +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.networks.single.SingleNetworkStatusFetcher import com.tangem.domain.quotes.QuotesRepository import com.tangem.domain.tokens.repository.CurrenciesRepository @@ -15,8 +16,6 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Suppress("TooManyFunctions") @@ -253,12 +252,12 @@ internal object YieldSupplyDomainModule { fun provideYieldSupplyPendingProcessorUseCase( yieldSupplyRepository: YieldSupplyRepository, singleNetworkStatusFetcher: SingleNetworkStatusFetcher, - dispatcherProvider: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): YieldSupplyPendingTracker { return YieldSupplyPendingTracker( yieldSupplyRepository = yieldSupplyRepository, singleNetworkStatusFetcher = singleNetworkStatusFetcher, - coroutineScope = CoroutineScope(SupervisorJob() + dispatcherProvider.io), + coroutineScope = appScope, ) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt index caf25e2b96..9736bca843 100644 --- a/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt @@ -34,6 +34,7 @@ import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey import com.tangem.domain.card.common.util.cardTypesResolver import com.tangem.domain.card.repository.CardSdkConfigRepository +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.models.scan.CardDTO @@ -65,7 +66,6 @@ import com.tangem.tap.domain.twins.CreateFirstTwinWalletTask import com.tangem.tap.domain.twins.CreateSecondTwinWalletTask import com.tangem.tap.domain.twins.FinalizeTwinTask import com.tangem.tap.domain.visa.VisaCardScanHandler -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.wallet.R import kotlinx.coroutines.* import kotlinx.coroutines.sync.Mutex @@ -86,7 +86,7 @@ internal class DefaultTangemSdkManager( private val analyticsExceptionHandler: AnalyticsExceptionHandler, private val blockchainToDeriveFinder: BlockchainToDeriveFinder, private val analyticsEventHandler: AnalyticsEventHandler, - dispatchers: CoroutineDispatcherProvider, + private val coroutineScope: AppCoroutineScope, ) : TangemSdkManager { private val awaitInitializationMutex = Mutex() @@ -115,8 +115,6 @@ internal class DefaultTangemSdkManager( override val userCodeRequestPolicy: UserCodeRequestPolicy get() = tangemSdk.config.userCodeRequestPolicy - private val coroutineScope = CoroutineScope(SupervisorJob() + dispatchers.io) - override suspend fun checkNeedEnrollBiometrics(awaitInitialization: Boolean): Boolean { return try { needEnrollBiometrics diff --git a/app/src/test/kotlin/com/tangem/tap/common/analytics/appsflyer/AppsFlyerReferralParamsHandlerTest.kt b/app/src/test/kotlin/com/tangem/tap/common/analytics/appsflyer/AppsFlyerReferralParamsHandlerTest.kt index e83e93807b..42ca5e34cc 100644 --- a/app/src/test/kotlin/com/tangem/tap/common/analytics/appsflyer/AppsFlyerReferralParamsHandlerTest.kt +++ b/app/src/test/kotlin/com/tangem/tap/common/analytics/appsflyer/AppsFlyerReferralParamsHandlerTest.kt @@ -5,8 +5,8 @@ import com.tangem.datasource.local.appsflyer.AppsFlyerStore import com.tangem.domain.wallets.models.AppsFlyerConversionData import com.tangem.feature.referral.domain.SetShouldShowMobileWalletPromoUseCase import com.tangem.test.core.ProvideTestModels -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import arrow.core.right +import com.tangem.common.test.TestAppCoroutineScope import io.mockk.clearMocks import io.mockk.coEvery import io.mockk.coVerify @@ -30,7 +30,7 @@ class AppsFlyerReferralParamsHandlerTest { } private val handler = AppsFlyerReferralParamsHandler( appsFlyerStore = appsFlyerStore, - dispatchers = TestingCoroutineDispatcherProvider(), + coroutineScope = TestAppCoroutineScope(), setShouldShowMobileWalletPromoUseCase = setShouldShowMobileWalletPromoUseCase, ) diff --git a/common/test/src/main/java/com/tangem/common/test/TestAppCoroutineScope.kt b/common/test/src/main/java/com/tangem/common/test/TestAppCoroutineScope.kt new file mode 100644 index 0000000000..5baa3c239d --- /dev/null +++ b/common/test/src/main/java/com/tangem/common/test/TestAppCoroutineScope.kt @@ -0,0 +1,11 @@ +package com.tangem.common.test + +import com.tangem.utils.coroutines.AppCoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.test.TestScope +import kotlin.coroutines.CoroutineContext + +class TestAppCoroutineScope(override val coroutineContext: CoroutineContext = Dispatchers.Unconfined) : AppCoroutineScope { + + constructor(testScope: TestScope) : this(testScope.coroutineContext) +} \ No newline at end of file diff --git a/core/ab-tests/src/main/kotlin/com/tangem/core/abtests/di/ABTestsManagerModule.kt b/core/ab-tests/src/main/kotlin/com/tangem/core/abtests/di/ABTestsManagerModule.kt index 30c1e3b07e..79dde6cead 100644 --- a/core/ab-tests/src/main/kotlin/com/tangem/core/abtests/di/ABTestsManagerModule.kt +++ b/core/ab-tests/src/main/kotlin/com/tangem/core/abtests/di/ABTestsManagerModule.kt @@ -6,13 +6,11 @@ import com.tangem.core.abtests.manager.ABTestsManager import com.tangem.core.abtests.manager.impl.AmplitudeABTestsManager import com.tangem.core.abtests.manager.impl.StubABTestsManager import com.tangem.datasource.local.config.environment.EnvironmentConfig -import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.AppCoroutineScope import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -24,7 +22,7 @@ internal object ABTestsManagerModule { fun provideABTestsManager( application: Application, environmentConfig: EnvironmentConfig, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): ABTestsManager { return if (BuildConfig.AB_TESTS_ENABLED) { StubABTestsManager() @@ -32,7 +30,7 @@ internal object ABTestsManagerModule { AmplitudeABTestsManager( application = application, apiKey = environmentConfig.amplitudeApiKey, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ) } } diff --git a/core/ab-tests/src/main/kotlin/com/tangem/core/abtests/manager/impl/AmplitudeABTestsManager.kt b/core/ab-tests/src/main/kotlin/com/tangem/core/abtests/manager/impl/AmplitudeABTestsManager.kt index 2307363d90..703c717a79 100644 --- a/core/ab-tests/src/main/kotlin/com/tangem/core/abtests/manager/impl/AmplitudeABTestsManager.kt +++ b/core/ab-tests/src/main/kotlin/com/tangem/core/abtests/manager/impl/AmplitudeABTestsManager.kt @@ -7,14 +7,14 @@ import com.amplitude.experiment.ExperimentConfig import com.amplitude.experiment.ExperimentUser import com.tangem.core.abtests.manager.ABTestsManager import com.tangem.core.analytics.models.AnalyticsParam -import kotlinx.coroutines.CoroutineScope +import com.tangem.utils.coroutines.AppCoroutineScope import kotlinx.coroutines.launch import timber.log.Timber internal class AmplitudeABTestsManager( val application: Application, val apiKey: String, - val scope: CoroutineScope, + val scope: AppCoroutineScope, ) : ABTestsManager { private lateinit var client: ExperimentClient diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/managers/DevApiConfigsManager.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/managers/DevApiConfigsManager.kt index 3bbd41372d..d52c2d3a96 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/managers/DevApiConfigsManager.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/managers/DevApiConfigsManager.kt @@ -7,9 +7,7 @@ import com.tangem.datasource.api.common.config.ApiEnvironmentConfig import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.getObjectMap -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob +import com.tangem.utils.coroutines.AppCoroutineScope import kotlinx.coroutines.flow.* /** @@ -22,7 +20,7 @@ import kotlinx.coroutines.flow.* internal class DevApiConfigsManager( private val apiConfigs: ApiConfigs, private val appPreferencesStore: AppPreferencesStore, - private val dispatchers: CoroutineDispatcherProvider, + private val appScope: AppCoroutineScope, ) : MutableApiConfigsManager() { override val configs: StateFlow> @@ -51,7 +49,7 @@ internal class DevApiConfigsManager( notifyListeners(apiConfigs = apiConfigs, savedEnvironments = savedEnvironments) } - .launchIn(CoroutineScope(SupervisorJob() + dispatchers.default)) + .launchIn(appScope) } override fun getEnvironmentConfig(id: ApiConfig.ID): ApiEnvironmentConfig { diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/managers/MockApiConfigsManager.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/managers/MockApiConfigsManager.kt index 10318bb1d7..7f6fbccbfa 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/managers/MockApiConfigsManager.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/managers/MockApiConfigsManager.kt @@ -4,10 +4,22 @@ import com.tangem.datasource.api.common.config.ApiConfig import com.tangem.datasource.api.common.config.ApiConfigs import com.tangem.datasource.api.common.config.ApiEnvironment import com.tangem.datasource.api.common.config.ApiEnvironmentConfig -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob +import com.tangem.utils.coroutines.AppCoroutineScope import kotlinx.coroutines.flow.* +import kotlin.Boolean +import kotlin.String +import kotlin.Unit +import kotlin.collections.Map +import kotlin.collections.any +import kotlin.collections.associateWith +import kotlin.collections.component1 +import kotlin.collections.component2 +import kotlin.collections.first +import kotlin.collections.firstOrNull +import kotlin.collections.mapValues +import kotlin.collections.plus +import kotlin.error +import kotlin.to /** * Implementation of [ApiConfigsManager] in MOCK environment @@ -18,7 +30,7 @@ import kotlinx.coroutines.flow.* */ internal class MockApiConfigsManager( private val apiConfigs: ApiConfigs, - dispatchers: CoroutineDispatcherProvider, + private val coroutineScope: AppCoroutineScope, ) : MutableApiConfigsManager() { override val configs: StateFlow> @@ -26,8 +38,6 @@ internal class MockApiConfigsManager( override val initializedState: StateFlow = MutableStateFlow(value = true) - private val coroutineScope = CoroutineScope(SupervisorJob() + dispatchers.default) - override fun initialize() = Unit override fun getEnvironmentConfig(id: ApiConfig.ID): ApiEnvironmentConfig { diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/AppPreferencesStoreModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/AppPreferencesStoreModule.kt index d572234840..c5262e4825 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/AppPreferencesStoreModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/AppPreferencesStoreModule.kt @@ -3,6 +3,7 @@ package com.tangem.datasource.di import android.content.Context import com.squareup.moshi.Moshi import com.tangem.datasource.local.preferences.* +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides @@ -20,10 +21,11 @@ internal object AppPreferencesStoreModule { fun provideAppPreferencesStore( @ApplicationContext appContext: Context, dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, @SdkMoshi moshi: Moshi, ): AppPreferencesStore { return AppPreferencesStore( - preferencesDataStore = PreferencesDataStore.getInstance(context = appContext, dispatcher = dispatchers.io), + preferencesDataStore = PreferencesDataStore.getInstance(context = appContext, appScope = appScope), moshi = moshi, dispatchers = dispatchers, ) diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/ExpressAssetsStoreModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/ExpressAssetsStoreModule.kt index 512085bd3e..ef1befd7a1 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/ExpressAssetsStoreModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/ExpressAssetsStoreModule.kt @@ -11,14 +11,12 @@ import com.tangem.datasource.local.token.ExpressAssetsStore import com.tangem.datasource.utils.MoshiDataStoreSerializer import com.tangem.datasource.utils.listTypes import com.tangem.datasource.utils.mapWithStringKeyTypes -import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.AppCoroutineScope import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -30,7 +28,7 @@ internal object ExpressAssetsStoreModule { fun provideExpressAssetsStore( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): ExpressAssetsStore { return DefaultExpressAssetsStore( persistenceStore = DataStoreFactory.create( @@ -40,7 +38,7 @@ internal object ExpressAssetsStoreModule { defaultValue = emptyMap(), ), produceFile = { context.dataStoreFile("express_assets") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ), runtimeStore = RuntimeDataStore(), ) diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt index 25833cc27c..6689718905 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt @@ -25,7 +25,7 @@ import com.tangem.datasource.api.visa.VisaApi import com.tangem.datasource.di.utils.RetrofitApiBuilder import com.tangem.datasource.di.utils.RetrofitApiBuilder.Timeouts import com.tangem.datasource.local.preferences.AppPreferencesStore -import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.AppCoroutineScope import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -47,11 +47,11 @@ internal object NetworkModule { fun provideApiConfigManager( apiConfigs: ApiConfigs, appPreferencesStore: AppPreferencesStore, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): ApiConfigsManager { return when { - BuildConfig.BUILD_TYPE == MOCKED_BUILD_TYPE -> MockApiConfigsManager(apiConfigs, dispatchers) - BuildConfig.TESTER_MENU_ENABLED -> DevApiConfigsManager(apiConfigs, appPreferencesStore, dispatchers) + BuildConfig.BUILD_TYPE == MOCKED_BUILD_TYPE -> MockApiConfigsManager(apiConfigs, appScope) + BuildConfig.TESTER_MENU_ENABLED -> DevApiConfigsManager(apiConfigs, appPreferencesStore, appScope) else -> ProdApiConfigsManager(apiConfigs) } } diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/StakingStoreModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/StakingStoreModule.kt index d4bd6b3e65..25cedcd5bc 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/StakingStoreModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/StakingStoreModule.kt @@ -20,14 +20,12 @@ import com.tangem.datasource.utils.MoshiDataStoreSerializer import com.tangem.datasource.utils.listTypes import com.tangem.datasource.utils.mapWithStringKeyTypes import com.tangem.datasource.utils.setTypes -import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.AppCoroutineScope import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -39,7 +37,7 @@ internal object StakingStoreModule { fun provideStakingTokensStore( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): StakingYieldsStore { return DefaultStakingYieldsStore( dataStore = DataStoreFactory.create( @@ -49,7 +47,7 @@ internal object StakingStoreModule { defaultValue = emptyList(), ), produceFile = { context.dataStoreFile(fileName = "yields_cache") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ), ) } @@ -59,7 +57,7 @@ internal object StakingStoreModule { fun provideYieldsBalancesPersistenceStore( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): DataStore>> { return DataStoreFactory.create( serializer = MoshiDataStoreSerializer( @@ -68,7 +66,7 @@ internal object StakingStoreModule { defaultValue = emptyMap(), ), produceFile = { context.dataStoreFile(fileName = "yield_balances") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ) } @@ -83,7 +81,7 @@ internal object StakingStoreModule { fun provideP2PEthPoolBalancesPersistenceStore( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): DataStore>> { return DataStoreFactory.create( serializer = MoshiDataStoreSerializer( @@ -92,7 +90,7 @@ internal object StakingStoreModule { defaultValue = emptyMap(), ), produceFile = { context.dataStoreFile(fileName = "p2p_eth_pool_balances") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ) } @@ -101,7 +99,7 @@ internal object StakingStoreModule { fun provideP2PEthPoolVaultsStore( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): P2PEthPoolVaultsStore { return DefaultP2PEthPoolVaultsStore( dataStore = DataStoreFactory.create( @@ -111,7 +109,7 @@ internal object StakingStoreModule { defaultValue = emptyList(), ), produceFile = { context.dataStoreFile(fileName = "p2p_eth_pool_vaults") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ), ) } diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/TokenReceiveWarningModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/TokenReceiveWarningModule.kt index c0aa4159dd..03cc572506 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/TokenReceiveWarningModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/TokenReceiveWarningModule.kt @@ -8,14 +8,12 @@ import com.tangem.datasource.local.token.DefaultTokenReceiveWarningActionStore import com.tangem.datasource.local.token.TokenReceiveWarningActionStore import com.tangem.datasource.utils.MoshiDataStoreSerializer import com.tangem.datasource.utils.setTypes -import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.AppCoroutineScope import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -27,7 +25,7 @@ object TokenReceiveWarningModule { fun provideTokenReceiveWarningStore( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): TokenReceiveWarningActionStore { return DefaultTokenReceiveWarningActionStore( persistenceStore = DataStoreFactory.create( @@ -37,7 +35,7 @@ object TokenReceiveWarningModule { defaultValue = emptySet(), ), produceFile = { context.dataStoreFile(fileName = "token_receive_warnings_viewed") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ), ) } diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/WalletConnectModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/WalletConnectModule.kt index e790ce4dc7..33d36f1edd 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/WalletConnectModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/WalletConnectModule.kt @@ -8,16 +8,14 @@ import com.tangem.datasource.local.walletconnect.DefaultWalletConnectStore import com.tangem.datasource.local.walletconnect.WalletConnectStore import com.tangem.datasource.utils.MoshiDataStoreSerializer import com.tangem.datasource.utils.setTypes +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.walletconnect.model.WcPendingApprovalSessionDTO import com.tangem.domain.walletconnect.model.WcSessionDTO -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -29,9 +27,8 @@ object WalletConnectModule { fun provideWalletConnectStore( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + scope: AppCoroutineScope, ): WalletConnectStore { - val scope = CoroutineScope(context = dispatchers.io + SupervisorJob()) return DefaultWalletConnectStore( persistenceStore = DataStoreFactory.create( serializer = MoshiDataStoreSerializer( diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/YieldSupplyModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/YieldSupplyModule.kt index 179051f898..cb14310516 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/YieldSupplyModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/YieldSupplyModule.kt @@ -9,14 +9,12 @@ import com.tangem.datasource.local.yieldsupply.DefaultYieldMarketsStore import com.tangem.datasource.local.yieldsupply.YieldMarketsStore import com.tangem.datasource.utils.MoshiDataStoreSerializer import com.tangem.datasource.utils.listTypes -import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.AppCoroutineScope import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -28,7 +26,7 @@ object YieldSupplyModule { fun provideYieldMarketsStore( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): YieldMarketsStore { return DefaultYieldMarketsStore( persistenceStore = DataStoreFactory.create( @@ -38,7 +36,7 @@ object YieldSupplyModule { defaultValue = emptyList(), ), produceFile = { context.dataStoreFile(fileName = "yield_markets_cache") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ), ) } diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/logs/AppLogsStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/logs/AppLogsStore.kt index 4cadac0967..007f386f0e 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/logs/AppLogsStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/logs/AppLogsStore.kt @@ -1,6 +1,7 @@ package com.tangem.datasource.local.logs import android.content.Context +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.* @@ -27,13 +28,9 @@ import javax.inject.Singleton class AppLogsStore @Inject constructor( @ApplicationContext private val applicationContext: Context, private val dispatchers: CoroutineDispatcherProvider, + private val scope: AppCoroutineScope, ) { - private val scope = CoroutineScope( - context = SupervisorJob() + dispatchers.io + - CoroutineExceptionHandler { _, error -> Timber.e("AppLogsStore.scope is failed $error") }, - ) - private val mutex = Mutex() private val zipMutex = Mutex() diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/nft/NFTPersistenceStoreFactory.kt b/core/datasource/src/main/java/com/tangem/datasource/local/nft/NFTPersistenceStoreFactory.kt index 2a5387357e..6b3694be92 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/nft/NFTPersistenceStoreFactory.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/nft/NFTPersistenceStoreFactory.kt @@ -10,12 +10,10 @@ import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.local.nft.custom.NFTPriceId import com.tangem.datasource.utils.MoshiDataStoreSerializer import com.tangem.datasource.utils.listTypes +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import java.lang.reflect.ParameterizedType import javax.inject.Inject import javax.inject.Singleton @@ -24,7 +22,7 @@ import javax.inject.Singleton class NFTPersistenceStoreFactory @Inject constructor( @NetworkMoshi private val moshi: Moshi, @ApplicationContext private val context: Context, - private val dispatchers: CoroutineDispatcherProvider, + private val appScope: AppCoroutineScope, ) { fun provide(userWalletId: UserWalletId, network: Network): NFTPersistenceStore { @@ -61,7 +59,7 @@ class NFTPersistenceStoreFactory @Inject constructor( defaultValue = defaultValue, ), produceFile = { context.dataStoreFile(fileName = fileName) }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ) private fun Network.ID.formatted(): String = rawId.value diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesDataStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesDataStore.kt index e91af36e84..72835aa183 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesDataStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesDataStore.kt @@ -16,10 +16,8 @@ import com.tangem.datasource.local.preferences.PreferencesKeys.IS_WALLET_SWAP_PR import com.tangem.datasource.local.preferences.PreferencesKeys.SHOULD_SHOW_RING_PROMO_KEY import com.tangem.datasource.local.preferences.utils.CleanupKeyMigration import com.tangem.datasource.local.preferences.utils.SharedPreferencesKeyMigration -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob +import com.tangem.utils.coroutines.AppCoroutineScope import timber.log.Timber -import kotlin.coroutines.CoroutineContext /** * Application preferences data store 'DataStore'. @@ -35,15 +33,15 @@ internal object PreferencesDataStore { private var INSTANCE: DataStore? = null - fun getInstance(context: Context, dispatcher: CoroutineContext): DataStore { - return INSTANCE ?: create(context, dispatcher).also { INSTANCE = it } + fun getInstance(context: Context, appScope: AppCoroutineScope): DataStore { + return INSTANCE ?: create(context, appScope).also { INSTANCE = it } } - private fun create(context: Context, dispatcher: CoroutineContext): DataStore { + private fun create(context: Context, appScope: AppCoroutineScope): DataStore { return PreferenceDataStoreFactory.create( corruptionHandler = createCorruptionHandler(), migrations = createMigrations(context = context), - scope = CoroutineScope(context = dispatcher + SupervisorJob()), + scope = appScope, produceFile = { context.preferencesDataStoreFile(name = PREFERENCES_FILE_NAME) }, ) } diff --git a/core/utils/src/main/java/com/tangem/utils/coroutines/AppCoroutineScope.kt b/core/utils/src/main/java/com/tangem/utils/coroutines/AppCoroutineScope.kt new file mode 100644 index 0000000000..e8f95bc46b --- /dev/null +++ b/core/utils/src/main/java/com/tangem/utils/coroutines/AppCoroutineScope.kt @@ -0,0 +1,5 @@ +package com.tangem.utils.coroutines + +import kotlinx.coroutines.CoroutineScope + +interface AppCoroutineScope : CoroutineScope \ No newline at end of file diff --git a/core/utils/src/main/java/com/tangem/utils/coroutines/DelayedWork.kt b/core/utils/src/main/java/com/tangem/utils/coroutines/DelayedWork.kt deleted file mode 100644 index 8c822c02ed..0000000000 --- a/core/utils/src/main/java/com/tangem/utils/coroutines/DelayedWork.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.tangem.utils.coroutines - -import javax.inject.Qualifier - -@Qualifier -@Retention(AnnotationRetention.BINARY) -annotation class DelayedWork \ No newline at end of file diff --git a/core/utils/src/main/java/com/tangem/utils/di/DelayedWorkCoroutineModule.kt b/core/utils/src/main/java/com/tangem/utils/di/DelayedWorkCoroutineModule.kt deleted file mode 100644 index 4f5ad6e74f..0000000000 --- a/core/utils/src/main/java/com/tangem/utils/di/DelayedWorkCoroutineModule.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.tangem.utils.di - -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import com.tangem.utils.coroutines.DelayedWork -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -object DelayedWorkCoroutineModule { - - @Provides - @Singleton - @DelayedWork - fun provideDelayedWorkCoroutineScope(coroutineDispatcherProvider: CoroutineDispatcherProvider): CoroutineScope { - return CoroutineScope(SupervisorJob() + coroutineDispatcherProvider.io) - } -} \ No newline at end of file diff --git a/data/account/src/main/kotlin/com/tangem/data/account/di/AccountDataModule.kt b/data/account/src/main/kotlin/com/tangem/data/account/di/AccountDataModule.kt index 5af224e026..b2ba244666 100644 --- a/data/account/src/main/kotlin/com/tangem/data/account/di/AccountDataModule.kt +++ b/data/account/src/main/kotlin/com/tangem/data/account/di/AccountDataModule.kt @@ -26,14 +26,13 @@ import com.tangem.datasource.utils.setTypes import com.tangem.domain.account.repository.AccountsCRUDRepository import com.tangem.domain.account.repository.AccountsExpandedRepository import com.tangem.domain.account.tokens.MainAccountTokensMigration +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -69,7 +68,7 @@ internal object AccountDataModule { fun provideAccountsExpandedRepository( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): AccountsExpandedRepository { val store = DataStoreFactory.create>>( serializer = MoshiDataStoreSerializer( @@ -78,7 +77,7 @@ internal object AccountDataModule { defaultValue = emptyMap(), ), produceFile = { context.dataStoreFile(fileName = "account_expanded_store") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ) return DefaultAccountsExpandedRepository( @@ -107,14 +106,14 @@ internal object AccountDataModule { userTokensSaver: UserTokensSaver, accountTokenMigrationStore: AccountTokenMigrationStore, eTagsStore: ETagsStore, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): DefaultMainAccountTokensMigration { return DefaultMainAccountTokensMigration( accountsResponseStoreFactory = accountsResponseStoreFactory, accountTokenMigrationStore = accountTokenMigrationStore, userTokensSaver = userTokensSaver, eTagsStore = eTagsStore, - dispatchers = dispatchers, + coroutineScope = appScope, ) } } \ No newline at end of file diff --git a/data/account/src/main/kotlin/com/tangem/data/account/store/AccountsResponseStoreFactory.kt b/data/account/src/main/kotlin/com/tangem/data/account/store/AccountsResponseStoreFactory.kt index df3f05aaa0..9beea3a5eb 100644 --- a/data/account/src/main/kotlin/com/tangem/data/account/store/AccountsResponseStoreFactory.kt +++ b/data/account/src/main/kotlin/com/tangem/data/account/store/AccountsResponseStoreFactory.kt @@ -10,11 +10,9 @@ import com.squareup.moshi.adapter import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.utils.MoshiDataStoreSerializer +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import java.util.concurrent.ConcurrentHashMap import javax.inject.Inject import javax.inject.Singleton @@ -35,7 +33,7 @@ typealias AccountsResponseStore = DataStore internal class AccountsResponseStoreFactory @Inject constructor( @ApplicationContext private val context: Context, @NetworkMoshi private val moshi: Moshi, - private val dispatchers: CoroutineDispatcherProvider, + private val appScope: AppCoroutineScope, ) { @OptIn(ExperimentalStdlibApi::class) @@ -53,7 +51,7 @@ internal class AccountsResponseStoreFactory @Inject constructor( DataStoreFactory.create( serializer = MoshiDataStoreSerializer(defaultValue = null, adapter = adapter), produceFile = { context.dataStoreFile(fileName = "wallet_accounts_${userWalletId.stringValue}") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ) } } diff --git a/data/account/src/main/kotlin/com/tangem/data/account/tokens/DefaultMainAccountTokensMigration.kt b/data/account/src/main/kotlin/com/tangem/data/account/tokens/DefaultMainAccountTokensMigration.kt index 3973b17662..b48fff6967 100644 --- a/data/account/src/main/kotlin/com/tangem/data/account/tokens/DefaultMainAccountTokensMigration.kt +++ b/data/account/src/main/kotlin/com/tangem/data/account/tokens/DefaultMainAccountTokensMigration.kt @@ -20,12 +20,10 @@ import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse import com.tangem.datasource.local.accounts.AccountTokenMigrationStore import com.tangem.datasource.utils.getSyncOrNull import com.tangem.domain.account.tokens.MainAccountTokensMigration +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.account.DerivationIndex import com.tangem.domain.models.wallet.UserWalletId import com.tangem.lib.crypto.derivation.AccountNodeRecognizer -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import timber.log.Timber @@ -43,11 +41,9 @@ internal class DefaultMainAccountTokensMigration( private val accountTokenMigrationStore: AccountTokenMigrationStore, private val userTokensSaver: UserTokensSaver, private val eTagsStore: ETagsStore, - dispatchers: CoroutineDispatcherProvider, + private val coroutineScope: AppCoroutineScope, ) : MainAccountTokensMigration { - private val coroutineScope = CoroutineScope(dispatchers.default + SupervisorJob()) - internal suspend fun migrate(userWalletId: UserWalletId): Either = either { val store = accountsResponseStoreFactory.create(userWalletId) val response = store.getSyncOrNull() diff --git a/data/account/src/test/java/com/tangem/data/account/store/AccountsResponseStoreFactoryTest.kt b/data/account/src/test/java/com/tangem/data/account/store/AccountsResponseStoreFactoryTest.kt index 6c39f7181c..f0fa74d20a 100644 --- a/data/account/src/test/java/com/tangem/data/account/store/AccountsResponseStoreFactoryTest.kt +++ b/data/account/src/test/java/com/tangem/data/account/store/AccountsResponseStoreFactoryTest.kt @@ -3,8 +3,8 @@ package com.tangem.data.account.store import android.content.Context import com.google.common.truth.Truth import com.squareup.moshi.Moshi +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.clearMocks import io.mockk.mockk import org.junit.jupiter.api.AfterEach @@ -19,7 +19,7 @@ class AccountsResponseStoreFactoryTest { private val factory: AccountsResponseStoreFactory = AccountsResponseStoreFactory( context = context, moshi = moshi, - dispatchers = TestingCoroutineDispatcherProvider(), + appScope = TestAppCoroutineScope(), ) @AfterEach diff --git a/data/account/src/test/java/com/tangem/data/account/token/DefaultMainAccountTokensMigrationTest.kt b/data/account/src/test/java/com/tangem/data/account/token/DefaultMainAccountTokensMigrationTest.kt index 70d14974b1..5b1401f2b3 100644 --- a/data/account/src/test/java/com/tangem/data/account/token/DefaultMainAccountTokensMigrationTest.kt +++ b/data/account/src/test/java/com/tangem/data/account/token/DefaultMainAccountTokensMigrationTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.account.token import arrow.core.right +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.data.account.converter.createGetWalletAccountsResponse import com.tangem.data.account.converter.createWalletAccountDTO import com.tangem.data.account.store.AccountsResponseStore @@ -18,7 +19,6 @@ import com.tangem.domain.models.wallet.UserWalletId import com.tangem.test.core.assertEither import com.tangem.test.core.assertEitherLeft import com.tangem.test.core.assertEitherRight -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest @@ -43,7 +43,7 @@ class DefaultMainAccountTokensMigrationTest { accountTokenMigrationStore = accountTokenMigrationStore, userTokensSaver = userTokensSaver, eTagsStore = eTagsStore, - dispatchers = TestingCoroutineDispatcherProvider(), + coroutineScope = TestAppCoroutineScope(), ) private val userWalletId = UserWalletId("011") diff --git a/data/common/src/main/kotlin/com/tangem/data/common/di/DataCommonModule.kt b/data/common/src/main/kotlin/com/tangem/data/common/di/DataCommonModule.kt index d30a846e5f..e963742c1b 100644 --- a/data/common/src/main/kotlin/com/tangem/data/common/di/DataCommonModule.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/di/DataCommonModule.kt @@ -13,6 +13,7 @@ import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.local.appsflyer.AppsFlyerStore import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.domain.common.wallets.UserWalletsListRepository +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.demo.models.DemoConfig import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.repository.WalletsRepository @@ -22,8 +23,6 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -69,6 +68,7 @@ internal object DataCommonModule { dispatchers: CoroutineDispatcherProvider, addressesEnricher: UserTokensResponseAddressesEnricher, walletServerBinder: WalletServerBinder, + appScope: AppCoroutineScope, ): UserTokensSaver { return UserTokensSaver( tangemTechApi = tangemTechApi, @@ -76,7 +76,7 @@ internal object DataCommonModule { dispatchers = dispatchers, addressesEnricher = addressesEnricher, pushTokensRetryerPool = RetryerPool( - coroutineScope = CoroutineScope(SupervisorJob() + dispatchers.default), + coroutineScope = appScope, ), walletServerBinder = walletServerBinder, ) diff --git a/data/common/src/test/kotlin/com/tangem/data/common/quote/DefaultQuotesFetcherTest.kt b/data/common/src/test/kotlin/com/tangem/data/common/quote/DefaultQuotesFetcherTest.kt index 0569178c46..dd54dc9e0d 100644 --- a/data/common/src/test/kotlin/com/tangem/data/common/quote/DefaultQuotesFetcherTest.kt +++ b/data/common/src/test/kotlin/com/tangem/data/common/quote/DefaultQuotesFetcherTest.kt @@ -151,7 +151,7 @@ internal class DefaultQuotesFetcherTest { quotes = setOf( QuoteMetadata( cryptoCurrencyId = "ethereum", - timestamp = DateTime.now().millis - 10_000, + timestamp = DateTime.now().millis - 20_000, value = cachedQuote, ), ), @@ -194,7 +194,7 @@ internal class DefaultQuotesFetcherTest { quotes = setOf( QuoteMetadata( cryptoCurrencyId = "ethereum", - timestamp = DateTime.now().millis - 10_000, + timestamp = DateTime.now().millis - 20_000, value = cachedQuote, ), QuoteMetadata( @@ -385,7 +385,7 @@ internal class DefaultQuotesFetcherTest { quotes = setOf( QuoteMetadata( cryptoCurrencyId = "solana", - timestamp = DateTime.now().millis - 10_000, + timestamp = DateTime.now().millis - 20_000, value = MockQuoteResponseFactory.createSinglePrice(BigDecimal.ZERO), ), ), diff --git a/data/networks/src/main/java/com/tangem/data/networks/di/NetworkDataModule.kt b/data/networks/src/main/java/com/tangem/data/networks/di/NetworkDataModule.kt index 43648cfd89..e97384ee27 100644 --- a/data/networks/src/main/java/com/tangem/data/networks/di/NetworkDataModule.kt +++ b/data/networks/src/main/java/com/tangem/data/networks/di/NetworkDataModule.kt @@ -15,6 +15,7 @@ import com.tangem.datasource.local.network.entity.NetworkStatusDM import com.tangem.datasource.utils.MoshiDataStoreSerializer import com.tangem.datasource.utils.mapWithStringKeyTypes import com.tangem.datasource.utils.setTypes +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.networks.repository.NetworksRepository import com.tangem.domain.networks.utils.NetworksCleaner import com.tangem.domain.walletmanager.WalletManagersFacade @@ -24,8 +25,6 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -37,7 +36,7 @@ internal object NetworkDataModule { fun provideNetworksStatusesStore( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): NetworksStatusesStore { return DefaultNetworksStatusesStore( context = context, @@ -49,9 +48,9 @@ internal object NetworkDataModule { defaultValue = emptyMap(), ), produceFile = { context.dataStoreFile(fileName = "networks_statuses_2") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ), - dispatchers = dispatchers, + scope = appScope, ) } diff --git a/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStore.kt b/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStore.kt index 7961e06c77..0cb7dba076 100644 --- a/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStore.kt +++ b/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStore.kt @@ -7,11 +7,11 @@ import com.tangem.data.networks.converters.SimpleNetworkStatusConverter import com.tangem.data.networks.models.SimpleNetworkStatus import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.datasource.local.network.entity.NetworkStatusDM +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.StatusSource import com.tangem.domain.models.network.Network import com.tangem.domain.models.network.NetworkStatus import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.addOrReplace import kotlinx.coroutines.* import kotlinx.coroutines.flow.* @@ -33,11 +33,9 @@ internal class DefaultNetworksStatusesStore( context: Context, private val runtimeStore: RuntimeSharedStore, private val persistenceDataStore: DataStore, - dispatchers: CoroutineDispatcherProvider, + private val scope: AppCoroutineScope, ) : NetworksStatusesStore { - private val scope = CoroutineScope(context = SupervisorJob() + dispatchers.io) - init { scope.launch { try { diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/GetTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/GetTest.kt index 7a8ab68799..1408149256 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/GetTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/GetTest.kt @@ -2,6 +2,7 @@ package com.tangem.data.networks.store import com.google.common.truth.Truth import com.tangem.blockchain.common.Blockchain +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.common.test.domain.network.MockNetworkStatusFactory import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory @@ -10,7 +11,6 @@ import com.tangem.data.networks.toSimple import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.domain.models.wallet.UserWalletId import com.tangem.test.core.getEmittedValues -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.mockk import kotlinx.coroutines.test.runTest import org.junit.Test @@ -27,7 +27,7 @@ internal class GetTest { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/InitializationTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/InitializationTest.kt index 63d2daa46b..c28121a1f5 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/InitializationTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/InitializationTest.kt @@ -2,6 +2,7 @@ package com.tangem.data.networks.store import androidx.datastore.core.DataStore import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.common.test.domain.network.MockNetworkStatusFactory import com.tangem.data.networks.models.SimpleNetworkStatus @@ -10,7 +11,6 @@ import com.tangem.data.networks.toSimple import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.domain.models.StatusSource import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.flow.emptyFlow @@ -33,7 +33,7 @@ internal class InitializationTest { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(null) @@ -48,7 +48,7 @@ internal class InitializationTest { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(emptyMap>()) @@ -71,7 +71,7 @@ internal class InitializationTest { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) val expectedStatus = status.toSimple().copy(value = status.value.copySealed(source = StatusSource.CACHE)) diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreStatusTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreStatusTest.kt index d310e1bdde..84b5a3d6bb 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreStatusTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreStatusTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.networks.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.common.test.domain.network.MockNetworkStatusFactory import com.tangem.data.networks.models.SimpleNetworkStatus @@ -10,7 +11,6 @@ import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.domain.models.StatusSource import com.tangem.domain.models.network.NetworkStatus import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.mockk import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.test.runTest @@ -31,7 +31,7 @@ internal class ParameterizedStoreStatusTest(private val model: Model) { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreSuccessTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreSuccessTest.kt index 7e62ff9843..513a4c0b55 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreSuccessTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreSuccessTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.networks.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.common.test.domain.network.MockNetworkStatusFactory import com.tangem.data.networks.models.SimpleNetworkStatus @@ -10,7 +11,6 @@ import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.domain.models.StatusSource import com.tangem.domain.models.network.NetworkStatus import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.mockk import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.test.runTest @@ -31,7 +31,7 @@ internal class ParameterizedStoreSuccessTest(private val model: Model) { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreTest.kt index 99436f876e..543ab9a7c6 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/ParameterizedStoreTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.networks.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.common.test.domain.network.MockNetworkStatusFactory import com.tangem.data.networks.models.SimpleNetworkStatus @@ -9,7 +10,6 @@ import com.tangem.data.networks.toSimple import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.domain.models.network.NetworkStatus import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.mockk import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.test.runTest @@ -30,7 +30,7 @@ internal class ParameterizedStoreTest(private val model: Model) { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/SetSourceAsCacheTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/SetSourceAsCacheTest.kt index cfb2eb16f0..405cbcf352 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/SetSourceAsCacheTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/SetSourceAsCacheTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.networks.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.common.test.domain.network.MockNetworkStatusFactory import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory @@ -10,7 +11,6 @@ import com.tangem.datasource.local.network.entity.NetworkStatusDM import com.tangem.domain.models.StatusSource import com.tangem.domain.models.network.NetworkStatus import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.mockk import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.test.runTest @@ -28,7 +28,7 @@ internal class SetSourceAsCacheTest { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/SetSourceAsOnlyCacheTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/SetSourceAsOnlyCacheTest.kt index 1136ce2921..df2021163d 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/SetSourceAsOnlyCacheTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/SetSourceAsOnlyCacheTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.networks.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.common.test.domain.network.MockNetworkStatusFactory import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory @@ -10,7 +11,6 @@ import com.tangem.datasource.local.network.entity.NetworkStatusDM import com.tangem.domain.models.StatusSource import com.tangem.domain.models.network.NetworkStatus import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.mockk import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.test.runTest @@ -28,7 +28,7 @@ internal class SetSourceAsOnlyCacheTest { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/StoreStatusTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/StoreStatusTest.kt index aa545d3ba4..52d06670d9 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/StoreStatusTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/StoreStatusTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.networks.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.common.test.domain.network.MockNetworkStatusFactory import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory @@ -10,7 +11,6 @@ import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.datasource.local.network.entity.NetworkStatusDM import com.tangem.domain.models.StatusSource import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.mockk import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.test.runTest @@ -28,7 +28,7 @@ internal class StoreStatusTest { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/StoreSuccessTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/StoreSuccessTest.kt index ebf54b27c7..40bdcbcad4 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/StoreSuccessTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/StoreSuccessTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.networks.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.common.test.domain.network.MockNetworkStatusFactory import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory @@ -9,7 +10,6 @@ import com.tangem.data.networks.toSimple import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.domain.models.StatusSource import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.mockk import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.test.runTest @@ -27,7 +27,7 @@ internal class StoreSuccessTest { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/StoreTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/StoreTest.kt index eb5cd705b3..b0bd11e6a7 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/StoreTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/StoreTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.networks.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.common.test.domain.network.MockNetworkStatusFactory import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory @@ -9,7 +10,6 @@ import com.tangem.data.networks.toSimple import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.domain.models.StatusSource import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.mockk import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.test.runTest @@ -27,7 +27,7 @@ internal class StoreTest { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/UpdateStatusSourceTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/UpdateStatusSourceTest.kt index 785c1b8d1b..703466e756 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/UpdateStatusSourceTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/UpdateStatusSourceTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.networks.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.common.test.domain.network.MockNetworkStatusFactory import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory @@ -13,7 +14,6 @@ import com.tangem.domain.models.StatusSource import com.tangem.domain.models.network.NetworkAddress import com.tangem.domain.models.network.NetworkStatus import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.mockk import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.test.runTest @@ -31,7 +31,7 @@ internal class UpdateStatusSourceTest { context = mockk(), runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultHotCryptoRepository.kt b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultHotCryptoRepository.kt index 735a95f01e..5f768924a0 100644 --- a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultHotCryptoRepository.kt +++ b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultHotCryptoRepository.kt @@ -22,6 +22,7 @@ import com.tangem.domain.card.common.extensions.canHandleToken import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.common.wallets.getSyncStrict import com.tangem.domain.common.wallets.loadAndGet +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.onramp.model.HotCryptoCurrency @@ -30,10 +31,9 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.JobHolder import com.tangem.utils.coroutines.runCatching import com.tangem.utils.coroutines.saveIn -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.flow.* +import kotlinx.coroutines.plus import timber.log.Timber /** @@ -59,9 +59,10 @@ internal class DefaultHotCryptoRepository( private val walletAccountsFetcher: WalletAccountsFetcher, private val dispatchers: CoroutineDispatcherProvider, private val analyticsEventHandler: AnalyticsEventHandler, + appScope: AppCoroutineScope, ) : HotCryptoRepository { - private val coroutineScope = CoroutineScope(dispatchers.main + SupervisorJob()) + private val coroutineScope = appScope + dispatchers.main private val hotCryptoJobHolder = JobHolder() diff --git a/data/onramp/src/main/java/com/tangem/data/onramp/di/OnrampDataModule.kt b/data/onramp/src/main/java/com/tangem/data/onramp/di/OnrampDataModule.kt index ca1ca2f6fc..7e95788c7a 100644 --- a/data/onramp/src/main/java/com/tangem/data/onramp/di/OnrampDataModule.kt +++ b/data/onramp/src/main/java/com/tangem/data/onramp/di/OnrampDataModule.kt @@ -28,6 +28,7 @@ import com.tangem.datasource.local.onramp.sepa.OnrampCurrentCountryByIPStore import com.tangem.datasource.local.onramp.sepa.OnrampSepaAvailabilityStore import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.domain.common.wallets.UserWalletsListRepository +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.onramp.repositories.* import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -109,6 +110,7 @@ internal object OnrampDataModule { dispatchers: CoroutineDispatcherProvider, analyticsEventHandler: AnalyticsEventHandler, walletAccountsFetcher: WalletAccountsFetcher, + appScope: AppCoroutineScope, ): HotCryptoRepository { return DefaultHotCryptoRepository( excludedBlockchains = excludedBlockchains, @@ -119,6 +121,7 @@ internal object OnrampDataModule { dispatchers = dispatchers, analyticsEventHandler = analyticsEventHandler, walletAccountsFetcher = walletAccountsFetcher, + appScope = appScope, ) } diff --git a/data/quotes/src/main/java/com/tangem/data/quotes/di/QuotesDataModule.kt b/data/quotes/src/main/java/com/tangem/data/quotes/di/QuotesDataModule.kt index 0cf87628bb..f7e09bf552 100644 --- a/data/quotes/src/main/java/com/tangem/data/quotes/di/QuotesDataModule.kt +++ b/data/quotes/src/main/java/com/tangem/data/quotes/di/QuotesDataModule.kt @@ -14,17 +14,15 @@ import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.datasource.utils.MoshiDataStoreSerializer import com.tangem.datasource.utils.mapWithStringKeyTypes +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.quotes.QuotesRepository import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher import com.tangem.domain.quotes.multi.MultiQuoteUpdater -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -36,7 +34,7 @@ internal object QuotesDataModule { fun provideQuotesStoreV2( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): QuotesStatusesStore { return DefaultQuotesStatusesStore( runtimeStore = RuntimeSharedStore(), @@ -47,9 +45,9 @@ internal object QuotesDataModule { defaultValue = emptyMap(), ), produceFile = { context.dataStoreFile(fileName = "quotes") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = appScope, ), - dispatchers = dispatchers, + scope = appScope, ) } @@ -65,13 +63,13 @@ internal object QuotesDataModule { appCurrencyResponseStore: AppCurrencyResponseStore, quotesStatusesStore: QuotesStatusesStore, multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - dispatchers: CoroutineDispatcherProvider, + coroutineScope: AppCoroutineScope, ): MultiQuoteUpdater { return DefaultMultiQuoteUpdater( appCurrencyResponseStore = appCurrencyResponseStore, quotesStatusesStore = quotesStatusesStore, multiQuoteStatusFetcher = multiQuoteStatusFetcher, - dispatchers = dispatchers, + coroutineScope = coroutineScope, ) } } \ No newline at end of file diff --git a/data/quotes/src/main/java/com/tangem/data/quotes/multi/DefaultMultiQuoteUpdater.kt b/data/quotes/src/main/java/com/tangem/data/quotes/multi/DefaultMultiQuoteUpdater.kt index 73e2446946..f499f8a4a0 100644 --- a/data/quotes/src/main/java/com/tangem/data/quotes/multi/DefaultMultiQuoteUpdater.kt +++ b/data/quotes/src/main/java/com/tangem/data/quotes/multi/DefaultMultiQuoteUpdater.kt @@ -4,16 +4,14 @@ import androidx.annotation.VisibleForTesting import arrow.core.left import com.tangem.data.quotes.store.QuotesStatusesStore import com.tangem.datasource.appcurrency.AppCurrencyResponseStore +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.core.utils.EitherFlow import com.tangem.domain.models.quote.QuoteStatus import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher import com.tangem.domain.quotes.multi.MultiQuoteUpdater -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.JobHolder import com.tangem.utils.coroutines.saveIn -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import timber.log.Timber @@ -32,10 +30,9 @@ internal class DefaultMultiQuoteUpdater( private val appCurrencyResponseStore: AppCurrencyResponseStore, private val quotesStatusesStore: QuotesStatusesStore, private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - dispatchers: CoroutineDispatcherProvider, + private val coroutineScope: AppCoroutineScope, ) : MultiQuoteUpdater { - private val coroutineScope = CoroutineScope(SupervisorJob() + dispatchers.default) private val updaterHolder = JobHolder() override fun subscribe() { diff --git a/data/quotes/src/main/java/com/tangem/data/quotes/store/DefaultQuotesStatusesStore.kt b/data/quotes/src/main/java/com/tangem/data/quotes/store/DefaultQuotesStatusesStore.kt index 52b464efa0..3225adfea6 100644 --- a/data/quotes/src/main/java/com/tangem/data/quotes/store/DefaultQuotesStatusesStore.kt +++ b/data/quotes/src/main/java/com/tangem/data/quotes/store/DefaultQuotesStatusesStore.kt @@ -4,13 +4,11 @@ import androidx.datastore.core.DataStore import com.tangem.data.quotes.converter.QuoteStatusConverter import com.tangem.datasource.api.tangemTech.models.QuotesResponse import com.tangem.datasource.local.datastore.RuntimeSharedStore +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.StatusSource import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.quote.QuoteStatus -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.addOrReplace -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.firstOrNull @@ -29,11 +27,9 @@ internal typealias CurrencyIdWithQuote = Map internal class DefaultQuotesStatusesStore( private val runtimeStore: RuntimeSharedStore>, private val persistenceDataStore: DataStore, - dispatchers: CoroutineDispatcherProvider, + private val scope: AppCoroutineScope, ) : QuotesStatusesStore { - private val scope = CoroutineScope(context = SupervisorJob() + dispatchers.io) - init { scope.launch { val cachedStatuses = persistenceDataStore.data.firstOrNull() diff --git a/data/quotes/src/test/java/com/tangem/data/quotes/multi/DefaultMultiQuoteStatusUpdaterTest.kt b/data/quotes/src/test/java/com/tangem/data/quotes/multi/DefaultMultiQuoteStatusUpdaterTest.kt index ecb0adfbb3..4126c45425 100644 --- a/data/quotes/src/test/java/com/tangem/data/quotes/multi/DefaultMultiQuoteStatusUpdaterTest.kt +++ b/data/quotes/src/test/java/com/tangem/data/quotes/multi/DefaultMultiQuoteStatusUpdaterTest.kt @@ -2,12 +2,12 @@ package com.tangem.data.quotes.multi import arrow.core.right import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.data.quotes.store.QuotesStatusesStore import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse import com.tangem.datasource.appcurrency.AppCurrencyResponseStore import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher import com.tangem.test.core.getEmittedValues -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.* import kotlinx.coroutines.flow.* import kotlinx.coroutines.test.runTest @@ -26,7 +26,7 @@ internal class DefaultMultiQuoteStatusUpdaterTest { appCurrencyResponseStore = appCurrencyResponseStore, quotesStatusesStore = quotesStore, multiQuoteStatusFetcher = multiQuoteStatusFetcher, - dispatchers = TestingCoroutineDispatcherProvider(), + coroutineScope = TestAppCoroutineScope(), ) @Test diff --git a/data/quotes/src/test/java/com/tangem/data/quotes/store/QuotesStatusesStoreExtTest.kt b/data/quotes/src/test/java/com/tangem/data/quotes/store/QuotesStatusesStoreExtTest.kt index 583fd0c1ed..1d187c765b 100644 --- a/data/quotes/src/test/java/com/tangem/data/quotes/store/QuotesStatusesStoreExtTest.kt +++ b/data/quotes/src/test/java/com/tangem/data/quotes/store/QuotesStatusesStoreExtTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.quotes.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.data.quote.MockQuoteResponseFactory import com.tangem.common.test.data.quote.toDomain import com.tangem.common.test.datastore.MockStateDataStore @@ -9,7 +10,6 @@ import com.tangem.domain.models.StatusSource import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.quote.QuoteStatus import com.tangem.test.core.ProvideTestModels -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Nested @@ -39,7 +39,7 @@ internal class QuotesStatusesStoreExtTest { store = DefaultQuotesStatusesStore( runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) } diff --git a/data/quotes/src/test/java/com/tangem/data/quotes/store/QuotesStatusesStoreTest.kt b/data/quotes/src/test/java/com/tangem/data/quotes/store/QuotesStatusesStoreTest.kt index dd83f58209..67df2cab9e 100644 --- a/data/quotes/src/test/java/com/tangem/data/quotes/store/QuotesStatusesStoreTest.kt +++ b/data/quotes/src/test/java/com/tangem/data/quotes/store/QuotesStatusesStoreTest.kt @@ -2,6 +2,7 @@ package com.tangem.data.quotes.store import androidx.datastore.core.DataStore import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.data.quote.MockQuoteResponseFactory import com.tangem.common.test.data.quote.toDomain import com.tangem.common.test.datastore.MockStateDataStore @@ -11,7 +12,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.quote.QuoteStatus import com.tangem.test.core.ProvideTestModels import com.tangem.test.core.getEmittedValues -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.flow.emptyFlow @@ -53,7 +53,7 @@ internal class QuotesStatusesStoreTest { store = DefaultQuotesStatusesStore( runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) } @@ -73,7 +73,7 @@ internal class QuotesStatusesStoreTest { DefaultQuotesStatusesStore( runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) val actual = runtimeStore.getSyncOrNull() @@ -93,7 +93,7 @@ internal class QuotesStatusesStoreTest { DefaultQuotesStatusesStore( runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) val actual = runtimeStore.getSyncOrNull() @@ -120,7 +120,7 @@ internal class QuotesStatusesStoreTest { DefaultQuotesStatusesStore( runtimeStore = runtimeStore, persistenceDataStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) val actual = runtimeStore.getSyncOrNull() diff --git a/data/staking/src/main/java/com/tangem/data/staking/di/StakingBalanceSupplierModule.kt b/data/staking/src/main/java/com/tangem/data/staking/di/StakingBalanceSupplierModule.kt index 60fd0250f8..4ddab5988c 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/di/StakingBalanceSupplierModule.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/di/StakingBalanceSupplierModule.kt @@ -8,11 +8,11 @@ import com.tangem.data.staking.store.StakeKitBalancesStore import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolAccountResponse import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO import com.tangem.datasource.local.datastore.RuntimeSharedStore +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.staking.multi.MultiStakingBalanceProducer import com.tangem.domain.staking.multi.MultiStakingBalanceSupplier import com.tangem.domain.staking.single.SingleStakingBalanceProducer import com.tangem.domain.staking.single.SingleStakingBalanceSupplier -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -27,12 +27,12 @@ internal object StakingBalanceSupplierModule { @Singleton fun provideStakingBalancesStore( persistenceStore: DataStore>>, - dispatchers: CoroutineDispatcherProvider, + scope: AppCoroutineScope, ): StakeKitBalancesStore { return DefaultStakeKitBalancesStore( runtimeStore = RuntimeSharedStore(), persistenceStore = persistenceStore, - dispatchers = dispatchers, + scope = scope, ) } @@ -40,12 +40,12 @@ internal object StakingBalanceSupplierModule { @Singleton fun provideP2PEthPoolBalancesStore( persistenceStore: DataStore>>, - dispatchers: CoroutineDispatcherProvider, + scope: AppCoroutineScope, ): P2PEthPoolBalancesStore { return DefaultP2PEthPoolBalancesStore( runtimeStore = RuntimeSharedStore(), persistenceStore = persistenceStore, - dispatchers = dispatchers, + scope = scope, ) } diff --git a/data/staking/src/main/java/com/tangem/data/staking/store/DefaultP2PEthPoolBalancesStore.kt b/data/staking/src/main/java/com/tangem/data/staking/store/DefaultP2PEthPoolBalancesStore.kt index d43261002e..c78065a255 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/store/DefaultP2PEthPoolBalancesStore.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/store/DefaultP2PEthPoolBalancesStore.kt @@ -4,14 +4,12 @@ import androidx.datastore.core.DataStore import com.tangem.data.staking.converters.ethpool.P2PEthPoolStakingBalanceConverter import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolAccountResponse import com.tangem.datasource.local.datastore.RuntimeSharedStore +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.StatusSource import com.tangem.domain.models.staking.StakingBalance import com.tangem.domain.models.staking.StakingID import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.addOrReplace -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.firstOrNull @@ -33,11 +31,9 @@ internal typealias WalletIdWithP2PEthPoolResponses = Map, private val persistenceStore: DataStore, - dispatchers: CoroutineDispatcherProvider, + private val scope: AppCoroutineScope, ) : P2PEthPoolBalancesStore { - private val scope = CoroutineScope(context = SupervisorJob() + dispatchers.io) - init { scope.launch { val cachedData = persistenceStore.data.firstOrNull() ?: return@launch diff --git a/data/staking/src/main/java/com/tangem/data/staking/store/DefaultStakeKitBalancesStore.kt b/data/staking/src/main/java/com/tangem/data/staking/store/DefaultStakeKitBalancesStore.kt index 16c5404a01..d26c1dee88 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/store/DefaultStakeKitBalancesStore.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/store/DefaultStakeKitBalancesStore.kt @@ -4,14 +4,12 @@ import androidx.datastore.core.DataStore import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.datasource.local.token.converter.StakingBalanceConverter +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.StatusSource import com.tangem.domain.models.staking.StakingBalance import com.tangem.domain.models.staking.StakingID import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.addOrReplace -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.firstOrNull @@ -33,11 +31,9 @@ internal typealias WalletIdWithStakingBalances = Map, private val persistenceStore: DataStore, - dispatchers: CoroutineDispatcherProvider, + private val scope: AppCoroutineScope, ) : StakeKitBalancesStore { - private val scope = CoroutineScope(context = SupervisorJob() + dispatchers.io) - init { scope.launch { val cachedStatuses = persistenceStore.data.firstOrNull() ?: return@launch diff --git a/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreGetMethodTest.kt b/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreGetMethodTest.kt index b3716181f1..ff524dd229 100644 --- a/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreGetMethodTest.kt +++ b/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreGetMethodTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.staking.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.data.staking.toDomain @@ -8,7 +9,6 @@ import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.domain.models.staking.StakingBalance import com.tangem.domain.models.wallet.UserWalletId import com.tangem.test.core.getEmittedValues -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import kotlinx.coroutines.test.runTest import org.junit.Test @@ -23,7 +23,7 @@ internal class StakingBalancesStoreGetMethodTest { private val store = DefaultStakeKitBalancesStore( runtimeStore = runtimeStore, persistenceStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreInitializationTest.kt b/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreInitializationTest.kt index 5ccbe2c608..32884813fa 100644 --- a/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreInitializationTest.kt +++ b/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreInitializationTest.kt @@ -2,13 +2,13 @@ package com.tangem.data.staking.store import androidx.datastore.core.DataStore import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.data.staking.toDomain import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.domain.models.staking.StakingBalance import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.flow.emptyFlow @@ -30,7 +30,7 @@ internal class StakingBalancesStoreInitializationTest { DefaultStakeKitBalancesStore( runtimeStore = runtimeStore, persistenceStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(null) @@ -44,7 +44,7 @@ internal class StakingBalancesStoreInitializationTest { DefaultStakeKitBalancesStore( runtimeStore = runtimeStore, persistenceStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(emptyMap>()) @@ -66,7 +66,7 @@ internal class StakingBalancesStoreInitializationTest { DefaultStakeKitBalancesStore( runtimeStore = runtimeStore, persistenceStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) val expected = mapOf(userWalletId to setOf(wrapper.toDomain())) diff --git a/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreUpdateMethodsTest.kt b/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreUpdateMethodsTest.kt index 602f2b4dc8..7f9ae0cdba 100644 --- a/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreUpdateMethodsTest.kt +++ b/data/staking/src/test/kotlin/com/tangem/data/staking/store/StakingBalancesStoreUpdateMethodsTest.kt @@ -1,6 +1,7 @@ package com.tangem.data.staking.store import com.google.common.truth.Truth +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory import com.tangem.common.test.datastore.MockStateDataStore import com.tangem.data.staking.toDomain @@ -10,7 +11,6 @@ import com.tangem.domain.models.StatusSource import com.tangem.domain.models.staking.StakingBalance import com.tangem.domain.models.staking.StakingID import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.test.runTest import org.junit.Test @@ -26,7 +26,7 @@ internal class StakingBalancesStoreUpdateMethodsTest { private val store = DefaultStakeKitBalancesStore( runtimeStore = runtimeStore, persistenceStore = persistenceStore, - dispatchers = TestingCoroutineDispatcherProvider(), + scope = TestAppCoroutineScope(), ) @Test diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayEligibilityManager.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayEligibilityManager.kt index c3eb76035e..32c5120681 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayEligibilityManager.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayEligibilityManager.kt @@ -2,6 +2,7 @@ package com.tangem.data.pay import com.tangem.common.card.FirmwareVersion import com.tangem.domain.common.wallets.UserWalletsListRepository +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.isLocked @@ -9,7 +10,6 @@ import com.tangem.domain.models.wallet.isMultiCurrency import com.tangem.domain.pay.TangemPayEligibilityManager import com.tangem.domain.pay.repository.OnboardingRepository import com.tangem.hot.sdk.model.HotWalletId -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.* import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.sync.Mutex @@ -17,15 +17,14 @@ import kotlinx.coroutines.sync.withLock import javax.inject.Inject internal class DefaultTangemPayEligibilityManager @Inject constructor( - dispatchers: CoroutineDispatcherProvider, private val userWalletsListRepository: UserWalletsListRepository, + private val coroutineScope: AppCoroutineScope, private val onboardingRepository: OnboardingRepository, ) : TangemPayEligibilityManager { private var cachedEligibleWallets: List? = null private var eligibleWalletsDeferred: Deferred>? = null private val loadMutex = Mutex() - private val coroutineScope = CoroutineScope(SupervisorJob() + dispatchers.default) init { resetDataWhenWalletsUpdate() diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/di/TangemPayDataModule.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/di/TangemPayDataModule.kt index 565fdbe700..c1842bbec1 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/di/TangemPayDataModule.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/di/TangemPayDataModule.kt @@ -18,6 +18,7 @@ import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.datasource.local.visa.entity.PaymentAccountStatusDM import com.tangem.datasource.utils.MoshiDataStoreSerializer import com.tangem.datasource.utils.mapWithStringKeyTypes +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.pay.TangemPayCryptoCurrencyFactory import com.tangem.domain.pay.TangemPayEligibilityManager import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher @@ -38,8 +39,6 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -112,6 +111,7 @@ internal interface TangemPayDataModule { @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, dispatchers: CoroutineDispatcherProvider, + scope: AppCoroutineScope, ): PaymentAccountStatusesStore { return PaymentAccountStatusesStore( runtimeStore = RuntimeSharedStore(), @@ -122,9 +122,9 @@ internal interface TangemPayDataModule { defaultValue = emptyMap(), ), produceFile = { context.dataStoreFile(fileName = "payment_account_statuses") }, - scope = CoroutineScope(context = dispatchers.io + SupervisorJob()), + scope = scope, ), - dispatchers = dispatchers, + scope = scope, ) } diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt index 61f222a421..0c0b28df99 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt @@ -19,6 +19,7 @@ import com.tangem.datasource.api.pay.models.response.FreezeUnfreezeCardResponse import com.tangem.datasource.api.pay.models.response.OrderResponse.Result.Status import com.tangem.datasource.local.visa.TangemPayCardFrozenStateStore import com.tangem.datasource.local.visa.TangemPayStorage +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.pay.model.SetPinResult import com.tangem.domain.pay.model.TangemPayCardBalance @@ -45,9 +46,9 @@ internal class DefaultTangemPayCardDetailsRepository @Inject constructor( private val storage: TangemPayStorage, private val cardFrozenStateStore: TangemPayCardFrozenStateStore, private val errorConverter: TangemPayErrorConverter, + private val pollingScope: AppCoroutineScope, ) : TangemPayCardDetailsRepository { - private val pollingScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) private val pollingJobs = mutableMapOf() private val storePollingMutex = Mutex() diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayWithdrawRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayWithdrawRepository.kt index 7bf21432a7..c88fd2fd38 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayWithdrawRepository.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayWithdrawRepository.kt @@ -9,6 +9,7 @@ import com.tangem.datasource.api.pay.models.request.WithdrawDataRequest import com.tangem.datasource.api.pay.models.request.WithdrawRequest import com.tangem.datasource.api.pay.models.response.WithdrawResponse import com.tangem.datasource.local.visa.TangemPayStorage +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.pay.TangemPayWithdrawExchangeState @@ -46,9 +47,9 @@ internal class DefaultTangemPayWithdrawRepository @Inject constructor( private val tangemPayStorage: TangemPayStorage, private val swapRepository: SwapRepository, private val orderRepository: CustomerOrderRepository, + private val withdrawPollingScope: AppCoroutineScope, ) : TangemPayWithdrawRepository { - private val withdrawPollingScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) private val withdrawPollingJobs = mutableMapOf() private val withdrawPollingMutex = Mutex() diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/store/PaymentAccountStatusesStore.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/store/PaymentAccountStatusesStore.kt index 5b8866a09a..4eec265d04 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/store/PaymentAccountStatusesStore.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/store/PaymentAccountStatusesStore.kt @@ -4,11 +4,9 @@ import androidx.datastore.core.DataStore import com.tangem.data.pay.converter.PaymentAccountStatusDMConverter import com.tangem.datasource.local.datastore.RuntimeSharedStore import com.tangem.datasource.local.visa.entity.PaymentAccountStatusDM +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.pay.PaymentAccountStatus -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.firstOrNull @@ -28,11 +26,9 @@ internal typealias WalletIdWithPaymentStatusDM = Map, private val persistenceDataStore: DataStore, - dispatchers: CoroutineDispatcherProvider, + private val scope: AppCoroutineScope, ) { - private val scope = CoroutineScope(context = SupervisorJob() + dispatchers.io) - init { scope.launch { try { diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt index b0012d93a3..8a0c2b7d45 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt @@ -17,7 +17,6 @@ import com.tangem.data.walletconnect.respond.WcRespondService import com.tangem.data.walletconnect.sessions.DefaultWcSessionsManager import com.tangem.data.walletconnect.utils.WcNamespaceConverter import com.tangem.data.walletconnect.utils.WcNetworksConverter -import com.tangem.data.walletconnect.utils.WcScope import com.tangem.datasource.di.SdkMoshi import com.tangem.datasource.local.walletconnect.WalletConnectStore import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier @@ -34,6 +33,7 @@ import com.tangem.domain.walletconnect.usecase.initialize.WcInitializeUseCase import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.usecase.GetWalletsUseCase +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides @@ -80,8 +80,8 @@ internal object WalletConnectDataModule { @Provides @Singleton - fun sdkDelegate(wcScope: WcScope, store: WalletConnectStore): WcPairSdkDelegate = WcPairSdkDelegate( - scope = wcScope, + fun sdkDelegate(appScope: AppCoroutineScope, store: WalletConnectStore): WcPairSdkDelegate = WcPairSdkDelegate( + scope = appScope, store = store, ) @@ -93,7 +93,7 @@ internal object WalletConnectDataModule { getWallets: GetWalletsUseCase, wcNetworksConverter: WcNetworksConverter, analytics: AnalyticsEventHandler, - wcScope: WcScope, + appScope: AppCoroutineScope, ): DefaultWcSessionsManager { return DefaultWcSessionsManager( store = store, @@ -101,7 +101,7 @@ internal object WalletConnectDataModule { getWallets = getWallets, wcNetworksConverter = wcNetworksConverter, analytics = analytics, - scope = wcScope, + scope = appScope, ) } @@ -109,10 +109,6 @@ internal object WalletConnectDataModule { @Singleton fun wcSessionsManager(default: DefaultWcSessionsManager): WcSessionsManager = default - @Provides - @Singleton - fun wcScope(dispatchers: CoroutineDispatcherProvider): WcScope = WcScope(dispatchers) - @Provides @Singleton fun wcRequestService(default: DefaultWcRequestService): WcRequestService = default diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/WcPairSdkDelegate.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/WcPairSdkDelegate.kt index a9d9030333..926afee1d3 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/WcPairSdkDelegate.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/WcPairSdkDelegate.kt @@ -6,13 +6,13 @@ import arrow.core.right import com.reown.walletkit.client.Wallet import com.reown.walletkit.client.WalletKit import com.tangem.data.walletconnect.utils.WC_TAG -import com.tangem.data.walletconnect.utils.WcScope import com.tangem.data.walletconnect.utils.WcSdkObserver import com.tangem.datasource.local.walletconnect.WalletConnectStore import com.tangem.data.walletconnect.utils.getDappOriginUrl import com.tangem.domain.walletconnect.model.WcPairError import com.tangem.domain.walletconnect.model.WcPairError.ApprovalFailed import com.tangem.domain.walletconnect.model.WcPendingApprovalSessionDTO +import com.tangem.utils.coroutines.AppCoroutineScope import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.awaitClose @@ -22,7 +22,7 @@ import kotlin.coroutines.resume import kotlin.time.Duration.Companion.seconds internal class WcPairSdkDelegate( - private val scope: WcScope, + private val scope: AppCoroutineScope, private val store: WalletConnectStore, ) : WcSdkObserver { diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt index 96a3982807..0d9625fc6f 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt @@ -15,6 +15,7 @@ import com.tangem.domain.walletconnect.model.WcSession import com.tangem.domain.walletconnect.model.WcSessionDTO import com.tangem.domain.walletconnect.repository.WcSessionsManager import com.tangem.domain.wallets.usecase.GetWalletsUseCase +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.* @@ -32,7 +33,7 @@ internal class DefaultWcSessionsManager( private val dispatchers: CoroutineDispatcherProvider, private val wcNetworksConverter: WcNetworksConverter, private val analytics: AnalyticsEventHandler, - private val scope: WcScope, + private val scope: AppCoroutineScope, ) : WcSessionsManager, WcSdkObserver { private val onSessionDelete = Channel(capacity = Channel.BUFFERED) diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcScope.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcScope.kt deleted file mode 100644 index d394ce320d..0000000000 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcScope.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.tangem.data.walletconnect.utils - -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob -import kotlin.coroutines.CoroutineContext - -internal class WcScope( - dispatchers: CoroutineDispatcherProvider, -) : CoroutineScope { - - override val coroutineContext: CoroutineContext = SupervisorJob() + dispatchers.io -} \ No newline at end of file diff --git a/data/wallets/src/main/java/com/tangem/data/wallets/hot/DefaultHotWalletAccessor.kt b/data/wallets/src/main/java/com/tangem/data/wallets/hot/DefaultHotWalletAccessor.kt index 62668755ef..039de11480 100644 --- a/data/wallets/src/main/java/com/tangem/data/wallets/hot/DefaultHotWalletAccessor.kt +++ b/data/wallets/src/main/java/com/tangem/data/wallets/hot/DefaultHotWalletAccessor.kt @@ -2,6 +2,7 @@ package com.tangem.data.wallets.hot import com.tangem.common.core.TangemSdkError import com.tangem.domain.common.wallets.UserWalletsListRepository +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.settings.repositories.LegacySettingsRepository @@ -11,10 +12,7 @@ import com.tangem.domain.wallets.repository.WalletsRepository import com.tangem.hot.sdk.TangemHotSdk import com.tangem.hot.sdk.exception.WrongPasswordException import com.tangem.hot.sdk.model.* -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.runSuspendCatching -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import java.util.concurrent.ConcurrentHashMap import javax.inject.Inject @@ -27,11 +25,9 @@ class DefaultHotWalletAccessor @Inject constructor( private val hotWalletPasswordRequester: HotWalletPasswordRequester, private val walletsRepository: WalletsRepository, private val legacySettingsRepository: LegacySettingsRepository, - dispatchers: CoroutineDispatcherProvider, + private val scope: AppCoroutineScope, ) : HotWalletAccessor { - private val scope = CoroutineScope(context = SupervisorJob() + dispatchers.io) - private val contextualUnlockHotWallet: ConcurrentHashMap = ConcurrentHashMap() override suspend fun signHashes(hotWalletId: HotWalletId, dataToSign: List): List = diff --git a/domain/account/status/build.gradle.kts b/domain/account/status/build.gradle.kts index 5d47d084f1..28daf7df24 100644 --- a/domain/account/status/build.gradle.kts +++ b/domain/account/status/build.gradle.kts @@ -36,6 +36,7 @@ dependencies { implementation(deps.kotlin.datetime) implementation(deps.kotlin.serialization) implementation(deps.timber) + implementation(deps.kermit) implementation(tangemDeps.blockchain) diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusListProducerFactoryModule.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusListProducerFactoryModule.kt index 30ae5b36ea..f7e4215b7b 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusListProducerFactoryModule.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusListProducerFactoryModule.kt @@ -1,7 +1,6 @@ package com.tangem.domain.account.status.di import com.tangem.domain.account.status.producer.* -import com.tangem.domain.core.flow.FlowProducerScope import com.tangem.domain.core.flow.FlowProducerTools import dagger.Binds import dagger.Module @@ -28,8 +27,4 @@ internal interface AccountStatusListProducerFactoryModule { @Binds @Singleton fun bindDefaultFlowProducerTools(impl: DefaultFlowProducerTools): FlowProducerTools - - @Binds - @Singleton - fun bindFlowProducerScope(impl: DefaultFlowProducerAppScope): FlowProducerScope } \ No newline at end of file diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusUseCaseModule.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusUseCaseModule.kt index 1f7bea813c..90ea428eda 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusUseCaseModule.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusUseCaseModule.kt @@ -8,6 +8,7 @@ import com.tangem.domain.account.status.utils.CryptoCurrencyBalanceFetcher import com.tangem.domain.account.status.utils.CryptoCurrencyMetadataCleaner import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.common.wallets.UserWalletsListRepository +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.express.ExpressServiceFetcher import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier @@ -26,8 +27,6 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -104,6 +103,7 @@ internal object AccountStatusUseCaseModule { cryptoCurrencyMetadataCleaner: CryptoCurrencyMetadataCleaner, expressServiceFetcher: ExpressServiceFetcher, dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): ManageCryptoCurrenciesUseCase { return ManageCryptoCurrenciesUseCase( singleAccountStatusListSupplier = singleAccountStatusListSupplier, @@ -114,7 +114,7 @@ internal object AccountStatusUseCaseModule { cryptoCurrencyBalanceFetcher = cryptoCurrencyBalanceFetcher, cryptoCurrencyMetadataCleaner = cryptoCurrencyMetadataCleaner, expressServiceFetcher = expressServiceFetcher, - parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.default), + parallelUpdatingScope = appScope, dispatchers = dispatchers, ) } @@ -126,14 +126,14 @@ internal object AccountStatusUseCaseModule { multiQuoteStatusFetcher: MultiQuoteStatusFetcher, multiStakingBalanceFetcher: MultiStakingBalanceFetcher, stakingIdFactory: StakingIdFactory, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): CryptoCurrencyBalanceFetcher { return CryptoCurrencyBalanceFetcher( multiNetworkStatusFetcher = multiNetworkStatusFetcher, multiQuoteStatusFetcher = multiQuoteStatusFetcher, multiStakingBalanceFetcher = multiStakingBalanceFetcher, stakingIdFactory = stakingIdFactory, - parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.default), + parallelUpdatingScope = appScope, ) } diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/producer/DefaultFlowProducerTools.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/producer/DefaultFlowProducerTools.kt index dfe0ea8bf4..e42901b839 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/producer/DefaultFlowProducerTools.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/producer/DefaultFlowProducerTools.kt @@ -1,54 +1,19 @@ package com.tangem.domain.account.status.producer +import co.touchlab.kermit.Logger import com.tangem.core.analytics.api.AnalyticsExceptionHandler import com.tangem.core.analytics.models.ExceptionAnalyticsEvent import com.tangem.domain.core.flow.FlowProducer -import com.tangem.domain.core.flow.FlowProducerScope import com.tangem.domain.core.flow.FlowProducerTools +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.CoroutineName -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* -import timber.log.Timber import javax.inject.Inject -import kotlin.coroutines.CoroutineContext - -class DefaultFlowProducerAppScope @Inject constructor( - dispatchers: CoroutineDispatcherProvider, - private val analyticsExceptionHandler: AnalyticsExceptionHandler, -) : FlowProducerScope { - - private val tag = "FlowProducerScope" - - override val coroutineContext: CoroutineContext = SupervisorJob() + - dispatchers.default + - CoroutineName(tag) + - CoroutineExceptionHandler { context, throwable -> - @Suppress("NullableToStringCall") - val coroutineName = context[CoroutineName]?.name.toString() - logError(throwable, coroutineName) - } - - private fun logError(throwable: Throwable, coroutineName: String) { - Timber.tag("FlowProducerExceptionHandler").e( - throwable, - "CoroutineName $coroutineName", - ) - val event = ExceptionAnalyticsEvent( - exception = throwable, - params = mapOf( - "source" to tag, - "coroutineName" to coroutineName, - ), - ) - analyticsExceptionHandler.sendException(event) - } -} class DefaultFlowProducerTools @Inject constructor( - private val scope: FlowProducerScope, + private val scope: AppCoroutineScope, + private val dispatchers: CoroutineDispatcherProvider, private val analyticsExceptionHandler: AnalyticsExceptionHandler, ) : FlowProducerTools { @@ -72,6 +37,7 @@ class DefaultFlowProducerTools @Inject constructor( } return upstream + .flowOn(dispatchers.default) .distinctUntilChanged() .shareIn( scope = scope, @@ -89,8 +55,8 @@ class DefaultFlowProducerTools @Inject constructor( private fun logError(cause: Throwable, flowProducerName: String, attempt: Long) { val tag = "FlowProducerRetryWhen" - Timber.tag(tag) - .e(cause, "flowProducerName $flowProducerName attempt $attempt") + Logger.withTag(tag) + .e("flowProducerName $flowProducerName attempt $attempt", cause) val event = ExceptionAnalyticsEvent( exception = cause, diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ManageCryptoCurrenciesUseCase.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ManageCryptoCurrenciesUseCase.kt index 2774fa49fe..5bb104ed00 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ManageCryptoCurrenciesUseCase.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ManageCryptoCurrenciesUseCase.kt @@ -8,6 +8,7 @@ import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.account.status.utils.CryptoCurrencyBalanceFetcher import com.tangem.domain.account.status.utils.CryptoCurrencyMetadataCleaner +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.core.utils.eitherOn import com.tangem.domain.express.ExpressServiceFetcher import com.tangem.domain.express.models.ExpressAsset @@ -51,7 +52,7 @@ class ManageCryptoCurrenciesUseCase( private val cryptoCurrencyBalanceFetcher: CryptoCurrencyBalanceFetcher, private val cryptoCurrencyMetadataCleaner: CryptoCurrencyMetadataCleaner, private val expressServiceFetcher: ExpressServiceFetcher, - private val parallelUpdatingScope: CoroutineScope, + private val parallelUpdatingScope: AppCoroutineScope, private val dispatchers: CoroutineDispatcherProvider, ) { diff --git a/domain/core/src/main/kotlin/com/tangem/domain/core/flow/FlowProducer.kt b/domain/core/src/main/kotlin/com/tangem/domain/core/flow/FlowProducer.kt index cf4c5e0474..3801a90e65 100644 --- a/domain/core/src/main/kotlin/com/tangem/domain/core/flow/FlowProducer.kt +++ b/domain/core/src/main/kotlin/com/tangem/domain/core/flow/FlowProducer.kt @@ -1,7 +1,6 @@ package com.tangem.domain.core.flow import arrow.core.Option -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharedFlow @@ -37,8 +36,6 @@ interface FlowProducer { } } -interface FlowProducerScope : CoroutineScope - interface FlowProducerTools { fun shareInProducer(flow: Flow, flowProducer: FlowProducer, withRetryWhen: Boolean = true): SharedFlow diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/SendTransactionUseCase.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/SendTransactionUseCase.kt index 05bc7a7445..b8b6b2cba7 100644 --- a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/SendTransactionUseCase.kt +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/SendTransactionUseCase.kt @@ -20,6 +20,7 @@ import com.tangem.domain.card.common.TapWorkarounds.isStart2Coin import com.tangem.domain.card.common.TapWorkarounds.isTangemTwins import com.tangem.domain.card.models.TwinKey import com.tangem.domain.card.repository.CardSdkConfigRepository +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.demo.DemoTransactionSender import com.tangem.domain.demo.models.DemoConfig import com.tangem.domain.models.network.Network @@ -31,7 +32,6 @@ import com.tangem.domain.transaction.error.SendTransactionError import com.tangem.domain.transaction.error.parseWrappedError import com.tangem.domain.transaction.models.EventTransactionTypeDto import com.tangem.domain.walletmanager.WalletManagersFacade -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -43,7 +43,7 @@ class SendTransactionUseCase( private val transactionRepository: TransactionRepository, private val walletManagersFacade: WalletManagersFacade, private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher, - private val parallelUpdatingScope: CoroutineScope, + private val parallelUpdatingScope: AppCoroutineScope, private val getHotWalletSigner: (UserWallet.Hot) -> TransactionSigner, private val pushNotificationsRepository: PushNotificationsRepository, ) { diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyPendingTracker.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyPendingTracker.kt index 299a8556cf..8693bae476 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyPendingTracker.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyPendingTracker.kt @@ -4,7 +4,7 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.networks.single.SingleNetworkStatusFetcher import com.tangem.domain.yield.supply.YieldSupplyRepository -import kotlinx.coroutines.CoroutineScope +import com.tangem.utils.coroutines.AppCoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.isActive @@ -26,7 +26,7 @@ import java.util.concurrent.ConcurrentHashMap class YieldSupplyPendingTracker( private val yieldSupplyRepository: YieldSupplyRepository, private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher, - private val coroutineScope: CoroutineScope, + private val coroutineScope: AppCoroutineScope, ) { private data class TrackedKey( diff --git a/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/usecase/YieldSupplyPendingTrackerTest.kt b/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/usecase/YieldSupplyPendingTrackerTest.kt index 81ee349867..e1c0349515 100644 --- a/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/usecase/YieldSupplyPendingTrackerTest.kt +++ b/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/usecase/YieldSupplyPendingTrackerTest.kt @@ -2,6 +2,7 @@ package com.tangem.domain.yield.supply.usecase import arrow.core.Either import com.google.common.truth.Truth.assertThat +import com.tangem.common.test.TestAppCoroutineScope import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWalletId @@ -36,7 +37,7 @@ class YieldSupplyPendingTrackerTest { useCase = YieldSupplyPendingTracker( yieldSupplyRepository = yieldSupplyRepository, singleNetworkStatusFetcher = singleNetworkStatusFetcher, - coroutineScope = testScope, + coroutineScope = TestAppCoroutineScope(testScope), ) } diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/SendBalanceUpdater.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/SendBalanceUpdater.kt index 0281f5bb8f..c8d81e1c83 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/SendBalanceUpdater.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/SendBalanceUpdater.kt @@ -1,17 +1,20 @@ package com.tangem.features.send.v2.common +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.nft.RefreshAllNFTUseCase import com.tangem.domain.tokens.FetchPendingTransactionsUseCase import com.tangem.domain.tokens.UpdateDelayedNetworkStatusUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase -import com.tangem.domain.models.wallet.UserWallet import com.tangem.features.txhistory.entity.TxHistoryContentUpdateEmitter -import com.tangem.utils.coroutines.DelayedWork import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import kotlinx.coroutines.* +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch @Suppress("LongParameterList") internal class SendBalanceUpdater @AssistedInject constructor( @@ -20,7 +23,7 @@ internal class SendBalanceUpdater @AssistedInject constructor( private val getTxHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase, private val txHistoryContentUpdateEmitter: TxHistoryContentUpdateEmitter, private val refreshAllNFTUseCase: RefreshAllNFTUseCase, - @DelayedWork private val coroutineScope: CoroutineScope, + private val coroutineScope: AppCoroutineScope, @Assisted private val userWallet: UserWallet, @Assisted private val cryptoCurrency: CryptoCurrency, ) { diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt index 805dafd774..d148b80650 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt @@ -40,6 +40,7 @@ import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.feedback.GetWalletMetaInfoUseCase import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase @@ -101,7 +102,6 @@ import com.tangem.utils.extensions.orZero import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking @@ -151,7 +151,7 @@ internal class StakingModel @Inject constructor( private val paramsInterceptorHolder: ParamsInterceptorHolder, private val shareManager: ShareManager, private val urlOpener: UrlOpener, - @DelayedWork private val coroutineScope: CoroutineScope, + private val coroutineScope: AppCoroutineScope, private val innerRouter: InnerStakingRouter, private val messageSender: UiMessageSender, private val giveApprovalFeatureToggles: GiveApprovalFeatureToggles, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt index 4c8bc0ceae..2128c11c3d 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt @@ -1,5 +1,6 @@ package com.tangem.features.staking.impl.presentation.state.helpers +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.staking.FetchActionsUseCase @@ -10,7 +11,6 @@ import com.tangem.domain.tokens.FetchCurrencyStatusUseCase import com.tangem.domain.tokens.FetchPendingTransactionsUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase import com.tangem.features.txhistory.entity.TxHistoryContentUpdateEmitter -import com.tangem.utils.coroutines.DelayedWork import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -24,7 +24,7 @@ internal class StakingBalanceUpdater @AssistedInject constructor( private val txHistoryContentUpdateEmitter: TxHistoryContentUpdateEmitter, private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, private val fetchStakingYieldBalanceUseCase: FetchStakingYieldBalanceUseCase, - @DelayedWork private val coroutineScope: CoroutineScope, + private val coroutineScope: AppCoroutineScope, @Assisted private val userWallet: UserWallet, @Assisted private val cryptoCurrencyStatus: CryptoCurrencyStatus, @Assisted private val integration: StakingIntegration, diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountListSortingSaver.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountListSortingSaver.kt index 52d5a6dbfc..f698a67127 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountListSortingSaver.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountListSortingSaver.kt @@ -2,12 +2,10 @@ package com.tangem.feature.walletsettings.utils import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.domain.account.usecase.ApplyAccountListSortingUseCase +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.domain.models.account.AccountId import com.tangem.domain.wallets.analytics.WalletSettingsAnalyticEvents -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.flow.* import timber.log.Timber import javax.inject.Inject @@ -27,15 +25,13 @@ import kotlin.time.Duration.Companion.seconds internal class AccountListSortingSaver @Inject constructor( private val applyAccountListSortingUseCase: ApplyAccountListSortingUseCase, private val analyticsEventHandler: AnalyticsEventHandler, - dispatchers: CoroutineDispatcherProvider, + private val coroutineScope: AppCoroutineScope, ) { /** Flow to hold the account IDs for sorting, with an initial null value. */ val accountsOrderFlow: StateFlow?> private field = MutableStateFlow?>(value = null) - private val coroutineScope = CoroutineScope(SupervisorJob() + dispatchers.io) - init { accountsOrderFlow .filterNotNull() diff --git a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/di/BlockchainSDKFactoryModule.kt b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/di/BlockchainSDKFactoryModule.kt index a8c5f4b3f5..4a6d0d0c5a 100644 --- a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/di/BlockchainSDKFactoryModule.kt +++ b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/di/BlockchainSDKFactoryModule.kt @@ -21,6 +21,7 @@ import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.local.config.environment.EnvironmentConfig import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.utils.coroutines.AppCoroutineScope import com.tangem.libs.blockchain_sdk.BuildConfig import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module @@ -28,8 +29,6 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -75,12 +74,12 @@ internal object BlockchainSDKFactoryModule { fun provideChangedBlockchainProvidersResponseDataStore( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - dispatchers: CoroutineDispatcherProvider, + appScope: AppCoroutineScope, ): DataStore { return DataStoreFactory.create( serializer = BlockchainProvidersResponseSerializer(moshi), produceFile = { context.dataStoreFile("changed_providers") }, - scope = CoroutineScope(dispatchers.io + SupervisorJob()), + scope = appScope, ) }