diff --git a/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt index b55ef9a8f7..e32ac8b237 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt @@ -10,7 +10,6 @@ import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.tokens.TokensFeatureToggles import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.tokens.repository.QuotesRepository import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -70,7 +69,6 @@ internal object ManageTokensDomainModule { customTokensRepository: CustomTokensRepository, walletManagersFacade: WalletManagersFacade, currenciesRepository: CurrenciesRepository, - networksRepository: NetworksRepository, derivationsRepository: DerivationsRepository, stakingRepository: StakingRepository, quotesRepository: QuotesRepository, @@ -83,7 +81,6 @@ internal object ManageTokensDomainModule { customTokensRepository = customTokensRepository, walletManagersFacade = walletManagersFacade, currenciesRepository = currenciesRepository, - networksRepository = networksRepository, derivationsRepository = derivationsRepository, stakingRepository = stakingRepository, quotesRepository = quotesRepository, diff --git a/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt index 7666729a36..9338ab2914 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt @@ -11,7 +11,6 @@ import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.tokens.TokensFeatureToggles import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.tokens.repository.QuotesRepository import com.tangem.domain.wallets.legacy.UserWalletsListManager import dagger.Module @@ -70,7 +69,6 @@ object MarketsDomainModule { derivationsRepository: DerivationsRepository, marketsTokenRepository: MarketsTokenRepository, currenciesRepository: CurrenciesRepository, - networksRepository: NetworksRepository, stakingRepository: StakingRepository, quotesRepository: QuotesRepository, multiNetworkStatusFetcher: MultiNetworkStatusFetcher, @@ -82,7 +80,6 @@ object MarketsDomainModule { derivationsRepository = derivationsRepository, marketsTokenRepository = marketsTokenRepository, currenciesRepository = currenciesRepository, - networksRepository = networksRepository, stakingRepository = stakingRepository, quotesRepository = quotesRepository, multiNetworkStatusFetcher = multiNetworkStatusFetcher, diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index ff23a2c9e2..d6e0a771ad 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -37,7 +37,6 @@ internal object TokensDomainModule { @Singleton fun provideAddCryptoCurrenciesUseCase( currenciesRepository: CurrenciesRepository, - networksRepository: NetworksRepository, stakingRepository: StakingRepository, quotesRepository: QuotesRepository, multiNetworkStatusFetcher: MultiNetworkStatusFetcher, @@ -47,7 +46,6 @@ internal object TokensDomainModule { ): AddCryptoCurrenciesUseCase { return AddCryptoCurrenciesUseCase( currenciesRepository = currenciesRepository, - networksRepository = networksRepository, stakingRepository = stakingRepository, quotesRepository = quotesRepository, multiNetworkStatusFetcher = multiNetworkStatusFetcher, @@ -62,7 +60,6 @@ internal object TokensDomainModule { fun provideFetchTokenListUseCase( currenciesRepository: CurrenciesRepository, quotesRepository: QuotesRepository, - networksRepository: NetworksRepository, stakingRepository: StakingRepository, multiNetworkStatusFetcher: MultiNetworkStatusFetcher, multiQuoteFetcher: MultiQuoteFetcher, @@ -71,7 +68,6 @@ internal object TokensDomainModule { ): FetchTokenListUseCase { return FetchTokenListUseCase( currenciesRepository = currenciesRepository, - networksRepository = networksRepository, quotesRepository = quotesRepository, stakingRepository = stakingRepository, multiNetworkStatusFetcher = multiNetworkStatusFetcher, @@ -121,8 +117,8 @@ internal object TokensDomainModule { fun provideGetCurrencyUseCase( baseCurrencyStatusOperations: BaseCurrencyStatusOperations, dispatchers: CoroutineDispatcherProvider, - ): GetCurrencyStatusUpdatesUseCase { - return GetCurrencyStatusUpdatesUseCase( + ): GetSingleCryptoCurrencyStatusUseCase { + return GetSingleCryptoCurrencyStatusUseCase( currencyStatusOperations = baseCurrencyStatusOperations, dispatchers = dispatchers, ) @@ -162,24 +158,11 @@ internal object TokensDomainModule { ) } - @Provides - @Singleton - fun provideGetPrimaryCurrencyUseCase( - currencyStatusOperations: BaseCurrencyStatusOperations, - dispatchers: CoroutineDispatcherProvider, - ): GetPrimaryCurrencyStatusUpdatesUseCase { - return GetPrimaryCurrencyStatusUpdatesUseCase( - currencyStatusOperations = currencyStatusOperations, - dispatchers = dispatchers, - ) - } - @Provides @Singleton fun provideFetchCurrencyStatusUseCase( currenciesRepository: CurrenciesRepository, quotesRepository: QuotesRepository, - networksRepository: NetworksRepository, stakingRepository: StakingRepository, singleNetworkStatusFetcher: SingleNetworkStatusFetcher, multiQuoteFetcher: MultiQuoteFetcher, @@ -188,7 +171,6 @@ internal object TokensDomainModule { ): FetchCurrencyStatusUseCase { return FetchCurrencyStatusUseCase( currenciesRepository = currenciesRepository, - networksRepository = networksRepository, quotesRepository = quotesRepository, stakingRepository = stakingRepository, singleNetworkStatusFetcher = singleNetworkStatusFetcher, @@ -203,7 +185,6 @@ internal object TokensDomainModule { fun provideFetchCardTokenListUseCase( currenciesRepository: CurrenciesRepository, quotesRepository: QuotesRepository, - networksRepository: NetworksRepository, stakingRepository: StakingRepository, multiNetworkStatusFetcher: MultiNetworkStatusFetcher, multiQuoteFetcher: MultiQuoteFetcher, @@ -212,7 +193,6 @@ internal object TokensDomainModule { ): FetchCardTokenListUseCase { return FetchCardTokenListUseCase( currenciesRepository = currenciesRepository, - networksRepository = networksRepository, quotesRepository = quotesRepository, stakingRepository = stakingRepository, multiNetworkStatusFetcher = multiNetworkStatusFetcher, @@ -222,14 +202,6 @@ internal object TokensDomainModule { ) } - @Provides - @Singleton - fun providesGetCryptoCurrencyStatusSyncUseCase( - currencyStatusOperations: BaseCurrencyStatusOperations, - ): GetCryptoCurrencyStatusSyncUseCase { - return GetCryptoCurrencyStatusSyncUseCase(currencyStatusOperations) - } - @Provides @Singleton fun provideGetCryptoCurrencyUseCase(currenciesRepository: CurrenciesRepository): GetCryptoCurrencyUseCase { @@ -328,14 +300,10 @@ internal object TokensDomainModule { @Provides @Singleton fun provideUpdateDelayedCurrencyStatusUseCase( - networksRepository: NetworksRepository, singleNetworkStatusFetcher: SingleNetworkStatusFetcher, - tokensFeatureToggles: TokensFeatureToggles, ): UpdateDelayedNetworkStatusUseCase { return UpdateDelayedNetworkStatusUseCase( - networksRepository = networksRepository, singleNetworkStatusFetcher = singleNetworkStatusFetcher, - tokensFeatureToggles = tokensFeatureToggles, ) } @@ -413,7 +381,6 @@ internal object TokensDomainModule { currenciesRepository: CurrenciesRepository, quotesRepository: QuotesRepository, quotesRepositoryV2: QuotesRepositoryV2, - networksRepository: NetworksRepository, stakingRepository: StakingRepository, singleNetworkStatusSupplier: SingleNetworkStatusSupplier, multiNetworkStatusSupplier: MultiNetworkStatusSupplier, @@ -427,7 +394,6 @@ internal object TokensDomainModule { currenciesRepository = currenciesRepository, quotesRepository = quotesRepository, quotesRepositoryV2 = quotesRepositoryV2, - networksRepository = networksRepository, stakingRepository = stakingRepository, singleNetworkStatusSupplier = singleNetworkStatusSupplier, multiNetworkStatusSupplier = multiNetworkStatusSupplier, @@ -447,7 +413,6 @@ internal object TokensDomainModule { currenciesRepository: CurrenciesRepository, quotesRepository: QuotesRepository, quotesRepositoryV2: QuotesRepositoryV2, - networksRepository: NetworksRepository, stakingRepository: StakingRepository, singleNetworkStatusSupplier: SingleNetworkStatusSupplier, multiNetworkStatusSupplier: MultiNetworkStatusSupplier, @@ -461,7 +426,6 @@ internal object TokensDomainModule { currenciesRepository = currenciesRepository, quotesRepository = quotesRepository, quotesRepositoryV2 = quotesRepositoryV2, - networksRepository = networksRepository, stakingRepository = stakingRepository, singleNetworkStatusSupplier = singleNetworkStatusSupplier, multiNetworkStatusSupplier = multiNetworkStatusSupplier, 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 b0b9e8f8ad..ea48365cb7 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,9 +4,7 @@ import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.demo.DemoConfig import com.tangem.domain.networks.single.SingleNetworkStatusFetcher import com.tangem.domain.networks.single.SingleNetworkStatusSupplier -import com.tangem.domain.tokens.TokensFeatureToggles import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.transaction.FeeRepository import com.tangem.domain.transaction.TransactionRepository import com.tangem.domain.transaction.usecase.* @@ -43,7 +41,6 @@ internal object TransactionDomainModule { transactionRepository: TransactionRepository, walletManagersFacade: WalletManagersFacade, singleNetworkStatusFetcher: SingleNetworkStatusFetcher, - tokensFeatureToggles: TokensFeatureToggles, ): SendTransactionUseCase { return SendTransactionUseCase( demoConfig = DemoConfig(), @@ -51,7 +48,6 @@ internal object TransactionDomainModule { transactionRepository = transactionRepository, walletManagersFacade = walletManagersFacade, singleNetworkStatusFetcher = singleNetworkStatusFetcher, - tokensFeatureToggles = tokensFeatureToggles, ) } @@ -61,17 +57,13 @@ internal object TransactionDomainModule { cardSdkConfigRepository: CardSdkConfigRepository, walletManagersFacade: WalletManagersFacade, currenciesRepository: CurrenciesRepository, - networksRepository: NetworksRepository, singleNetworkStatusSupplier: SingleNetworkStatusSupplier, - tokensFeatureToggles: TokensFeatureToggles, ): AssociateAssetUseCase { return AssociateAssetUseCase( cardSdkConfigRepository = cardSdkConfigRepository, walletManagersFacade = walletManagersFacade, currenciesRepository = currenciesRepository, - networksRepository = networksRepository, singleNetworkStatusSupplier = singleNetworkStatusSupplier, - tokensFeatureToggles = tokensFeatureToggles, ) } diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/DefaultTokensFeatureToggles.kt b/app/src/main/java/com/tangem/tap/domain/tokens/DefaultTokensFeatureToggles.kt index adc8e80741..bfb76fbf06 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/DefaultTokensFeatureToggles.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/DefaultTokensFeatureToggles.kt @@ -7,9 +7,6 @@ internal class DefaultTokensFeatureToggles( private val featureTogglesManager: FeatureTogglesManager, ) : TokensFeatureToggles { - override val isNetworksLoadingRefactoringEnabled: Boolean - get() = featureTogglesManager.isFeatureEnabled(name = "NETWORKS_LOADING_REFACTORING_ENABLED") - override val isQuotesLoadingRefactoringEnabled: Boolean get() = featureTogglesManager.isFeatureEnabled(name = "QUOTES_LOADING_REFACTORING_ENABLED") diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/DefaultLegacyWalletConnectRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/DefaultLegacyWalletConnectRepository.kt index 689db8c1c0..0ac30a5cb0 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/DefaultLegacyWalletConnectRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/DefaultLegacyWalletConnectRepository.kt @@ -13,6 +13,7 @@ import com.tangem.domain.walletconnect.WcPairService import com.tangem.domain.walletconnect.model.WcPairRequest import com.tangem.domain.walletconnect.model.legacy.Account import com.tangem.domain.walletconnect.usecase.initialize.WcInitializeUseCase +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.features.walletconnect.components.WalletConnectFeatureToggles import com.tangem.tap.common.analytics.events.WalletConnect import com.tangem.tap.domain.walletconnect2.app.TangemWcBlockchainHelper @@ -64,14 +65,18 @@ internal class DefaultLegacyWalletConnectRepositoryFacade constructor( if (isNewWc) stub.updateSessions() else legacy.updateSessions() } - override fun pair(uri: String, source: SourceType) { + override fun pair(userWalletId: UserWalletId, uri: String, source: SourceType) { val src = when (source) { SourceType.QR -> WcPairRequest.Source.QR SourceType.DEEPLINK -> WcPairRequest.Source.DEEPLINK SourceType.CLIPBOARD -> WcPairRequest.Source.CLIPBOARD SourceType.ETC -> WcPairRequest.Source.ETC } - if (isNewWc) wcPairService.pair(WcPairRequest(uri, src)) else legacy.pair(uri, source) + if (isNewWc) { + wcPairService.pair(WcPairRequest(uri = uri, source = src, userWalletId = userWalletId)) + } else { + legacy.pair(userWalletId = userWalletId, uri = uri, source = source) + } } override fun disconnect(topic: String) { @@ -110,7 +115,7 @@ internal class LegacyWalletConnectRepositoryStub : LegacyWalletConnectRepository override fun updateSessions() = Unit - override fun pair(uri: String, source: SourceType) = Unit + override fun pair(userWalletId: UserWalletId, uri: String, source: SourceType) = Unit override fun disconnect(topic: String) = Unit @@ -405,7 +410,7 @@ internal class DefaultLegacyWalletConnectRepository( this.userNamespaces = userNamespaces } - override fun pair(uri: String, source: SourceType) { + override fun pair(userWalletId: UserWalletId, uri: String, source: SourceType) { analyticsHandler.send(WalletConnect.NewSessionInitiated(source = source)) WalletKit.pair( params = Wallet.Params.Pair(uri), diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/LegacyWalletConnectRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/LegacyWalletConnectRepository.kt index 59d5954e00..c0e22a3b7d 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/LegacyWalletConnectRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/LegacyWalletConnectRepository.kt @@ -1,6 +1,7 @@ package com.tangem.tap.domain.walletconnect2.domain import com.tangem.domain.walletconnect.model.legacy.Account +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.tap.domain.walletconnect2.domain.models.* import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction.OpenSession.SourceType import kotlinx.coroutines.flow.Flow @@ -19,7 +20,7 @@ interface LegacyWalletConnectRepository { fun updateSessions() - fun pair(uri: String, source: SourceType) + fun pair(userWalletId: UserWalletId, uri: String, source: SourceType) fun disconnect(topic: String) diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt index d8d5a989ae..92418004d0 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt @@ -12,6 +12,7 @@ import com.tangem.domain.walletconnect.model.legacy.WalletConnectSessionsReposit import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.filterNotNull @@ -139,7 +140,11 @@ class WalletConnectInteractor( if (deeplinkStack.empty()) return val lastDeeplink = deeplinkStack.pop() val action = WalletConnectAction - .OpenSession(lastDeeplink, WalletConnectAction.OpenSession.SourceType.DEEPLINK) + .OpenSession( + wcUri = lastDeeplink, + source = WalletConnectAction.OpenSession.SourceType.DEEPLINK, + userWalletId = UserWalletId(userWalletId), + ) store.dispatchOnMain(action) }.onFailure { Timber.e("WC deeplink handling failed. $it") @@ -393,7 +398,11 @@ class WalletConnectInteractor( } if (isWalletConnectReadyForDeepLinks) { - val action = WalletConnectAction.OpenSession(deeplink, WalletConnectAction.OpenSession.SourceType.DEEPLINK) + val action = WalletConnectAction.OpenSession( + wcUri = deeplink, + source = WalletConnectAction.OpenSession.SourceType.DEEPLINK, + userWalletId = UserWalletId(userWalletId), + ) store.dispatchOnMain(action) } else { deeplinkStack.push(deeplink) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt index 7391c77f5b..4288f711b9 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.details.redux.walletconnect +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.tap.domain.walletconnect2.domain.WcPreparedRequest import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectError import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectEvents @@ -14,6 +15,7 @@ sealed class WalletConnectAction : Action { data class OpenSession( val wcUri: String, val source: SourceType, + val userWalletId: UserWalletId, ) : WalletConnectAction() { enum class SourceType { QR, DEEPLINK, CLIPBOARD, ETC } } diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt index 6bbd548de4..7439241a50 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt @@ -63,7 +63,11 @@ class WalletConnectMiddleware { is WalletConnectAction.OpenSession -> { val index = action.wcUri.indexOf("@") when (action.wcUri[index + 1]) { - '2' -> walletConnectRepository.pair(uri = action.wcUri, source = action.source) + '2' -> walletConnectRepository.pair( + uri = action.wcUri, + source = action.source, + userWalletId = action.userWalletId, + ) '1' -> { store.dispatchOnMain(WalletConnectAction.UnsupportedDappRequest) store.dispatchOnMain( diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt index 73a0989519..0974e0db1b 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt @@ -22,10 +22,10 @@ import org.rekotlin.StoreSubscriber @Suppress("UnusedPrivateMember") internal class DefaultWalletConnectComponent @AssistedInject constructor( @Assisted appComponentContext: AppComponentContext, - @Assisted params: Unit, + @Assisted params: WalletConnectComponent.Params, ) : WalletConnectComponent, AppComponentContext by appComponentContext, StoreSubscriber { - private val model: WalletConnectModel = getOrCreateModel() + private val model: WalletConnectModel = getOrCreateModel(params) private var screenState: MutableState = mutableStateOf(model.updateState(store.state.walletConnectState)) @@ -65,6 +65,9 @@ internal class DefaultWalletConnectComponent @AssistedInject constructor( @AssistedFactory interface Factory : WalletConnectComponent.Factory { - override fun create(context: AppComponentContext, params: Unit): DefaultWalletConnectComponent + override fun create( + context: AppComponentContext, + params: WalletConnectComponent.Params, + ): DefaultWalletConnectComponent } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectModel.kt index 21deae59a7..762b7afb71 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectModel.kt @@ -4,10 +4,12 @@ import androidx.compose.runtime.Stable import arrow.core.getOrElse import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.qrscanning.models.SourceType import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState +import com.tangem.tap.features.details.ui.walletconnect.api.WalletConnectComponent import com.tangem.tap.store import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.collections.immutable.toImmutableList @@ -22,13 +24,22 @@ import javax.inject.Inject internal class WalletConnectModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val listenToQrScanningUseCase: ListenToQrScanningUseCase, + paramsContainer: ParamsContainer, ) : Model() { + private val params = paramsContainer.require() + init { modelScope.launch { listenToQrScanningUseCase(SourceType.WALLET_CONNECT) .getOrElse { emptyFlow() } - .map { WalletConnectAction.OpenSession(it, WalletConnectAction.OpenSession.SourceType.QR) } + .map { + WalletConnectAction.OpenSession( + wcUri = it, + source = WalletConnectAction.OpenSession.SourceType.QR, + userWalletId = params.userWalletId, + ) + } .collect { store.dispatch(it) } } } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/api/WalletConnectComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/api/WalletConnectComponent.kt index 4e1f4ab3fb..6b9d8c4330 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/api/WalletConnectComponent.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/api/WalletConnectComponent.kt @@ -2,7 +2,9 @@ package com.tangem.tap.features.details.ui.walletconnect.api import com.tangem.core.decompose.factory.ComponentFactory import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.wallets.models.UserWalletId interface WalletConnectComponent : ComposableContentComponent { - interface Factory : ComponentFactory + data class Params(val userWalletId: UserWalletId) + interface Factory : ComponentFactory } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index 0f2b7d5303..f1cd71bbe3 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -291,13 +291,13 @@ internal class ChildFactory @Inject constructor( if (walletConnectFeatureToggles.isRedesignedWalletConnectEnabled) { createComponentChild( context = context, - params = Unit, + params = RedesignedWalletConnectComponent.Params(route.userWalletId), componentFactory = redesignedWalletConnectComponentFactory, ) } else { createComponentChild( context = context, - params = Unit, + params = WalletConnectComponent.Params(route.userWalletId), componentFactory = walletConnectComponentFactory, ) } diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index 0a280474be..af27366ceb 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -122,7 +122,7 @@ sealed class AppRoute(val path: String) : Route { } @Serializable - data object WalletConnectSessions : AppRoute(path = "/wallet_connect_sessions") + data class WalletConnectSessions(val userWalletId: UserWalletId) : AppRoute(path = "/wallet_connect_sessions") @Serializable data class QrScanning(val source: Source) : AppRoute(path = "/$source/qr_scanning${source.path}") { diff --git a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json index 239af3a94b..6a3b525e20 100644 --- a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json @@ -41,7 +41,7 @@ }, { "name": "NEW_ATTESTATION_ENABLED", - "version": "undefined" + "version": "5.24.0" }, { "name": "SEND_V2_ENABLED", @@ -51,10 +51,6 @@ "name": "WALLET_CONNECT_REDESIGN_ENABLED", "version": "undefined" }, - { - "name": "NETWORKS_LOADING_REFACTORING_ENABLED", - "version": "5.23.0" - }, { "name": "QUOTES_LOADING_REFACTORING_ENABLED", "version": "5.24.0" diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index aabccb9ff7..d3c9f55037 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -278,7 +278,7 @@ Kann nicht gegen %s ausgetauscht werden Bereitgestellt von Status - Tangem bietet Token-Swaps über Drittanbieter gemäß den jeweiligen Bedingungen des jeweiligen Anbieters an. + Anbieter erleichtern Transaktionen Anbieter Es ist ein Fehler aufgetreten. Code: %s Fehler %1$s. Der ausgewählte Anbieter kann die angegebene Transaktion nicht verarbeiten. Bitte runde den Wert auf %2$s auf oder änder diesen. @@ -319,11 +319,11 @@ Verifizierung erforderlich Wartet auf Transaktions-Hash Liste aller Token, die deiner Wallet hinzugefügt wurden - Beste Preise werden abgerufen … + Aktuelle Preise werden abgerufen ... Variabler Zinssatz Durch die Nutzung der Swap-Funktion erklärst du dich mit den folgenden Bedingungen des Anbieters einverstanden %s Durch die Nutzung der Swap-Funktionalität erklärst du dich mit des Anbieters %1$s und %2$s einverstanden - Weitere Anbieter werden bald folgen.\nBleib dabei! + Weitere Anbieter folgen in Kürze Anbieter Bester Preis Verfügbar bis zu %s @@ -419,6 +419,7 @@ Dieses Asset wird derzeit in der Wallet nicht unterstützt. Dieses Asset ist für dieses Wallet nicht verfügbar Hinzufügen + APY %s Verfügbare Netzwerke Mein Portfolio Markt @@ -448,6 +449,9 @@ Top-Gewinner Top-Verlierer Beliebt + Staking ist der einfachste Weg, um Belohnungen für Deine Kryptowährung zu erhalten. %s + Mehr anzeigen + Verdiene bis zu %s APY Über %s %d börse @@ -530,6 +534,13 @@ Basisinformationen Netzwerk Vertragsadresse + Kontrollabschnitt + Kontrollabschnitt + Kontrollabschnitt + Kontrollabschnitt + Kontrollabschnitt + Kontrollabschnitt + Kontrollabschnitt Letzter Verkaufspreis Raritätsetikett Seltenheitsgrad @@ -1051,6 +1062,8 @@ Validierer: %s Minimum %s Der Mindesttransaktionsbetrag beträgt %1$s. + Die Netzwerkgebühren für beliebte Token im Tron-Netzwerk können höher sein. Das Staking von TRX kann helfen, die Transaktionskosten zu senken. + Spare bei den Tron-Netzwerkgebühren Versuche es erneut Du hast dieselbe Karte oder Ring gescannt. Um ein Zwillings-Wallet zu erstellen, musst du die Karte oder Ring mit der Nummer %d scannen. Du hast die falsche Doppelkarte oder Ring gescannt. Bitte versuche eine andere Karte oder Ring @@ -1237,6 +1250,7 @@ Zeitüberschreitungsfehler. Bitte versuche es später erneut. WalletConnect konnte nicht hergestellt werden Diese Domäne kann nicht verifiziert werden. Überprüfe die Anfrage sorgfältig und bestätige diese dann. + Geh zurück zu Deinem Browser und stell erneut eine Verbindung über WalletConnect her. WalletConnect-Sitzung wurde getrennt Fehlercode: %s. Wenn das Problem weiterhin besteht, wende Dich bitte an unseren Support. Wir haben einen unbekannten Fehler festgestellt. @@ -1244,14 +1258,22 @@ Nicht unterstützte Netzwerke Tangem unterstützt ein erforderliches Netzwerk um %s. Verifizierte Domain + Falsche Karte oder falscher Ring in der Tangem-App ausgewählt Wir haben eine Art Problem + Verbinden Netzwerk Netzwerke Wallet + Verbundene Netzwerke + Anzeige des Kontostands und der Aktivitäten in Deiner Wallet Signiere die Transaktionen ohne eine Vorankündigung Genehmigung für Transaktionen anfordern Wird nicht in der Lage sein, + Möchte + Verbindungsanfrage Verbindungen + Inhalt + Daten kopieren Alle trennen Text über die Trennung aller dApps Alle dApps trennen @@ -1262,6 +1284,11 @@ Keine Sitzungen Diese Domain wird von mehreren Sicherheitsanbietern als unsicher eingestuft. Verlasse diese umgehend, um Dein Vermögen zu schützen. Bekanntes Sicherheitsrisiko + Anfrage von + Art der Signatur + Transaktionsanfrage + Transaktionsanfrage + Wallet verbinden Verwerfen Du hast eine unterbrochene Sicherung. Möchtest du diese fortsetzen? Ja, fortsetzen diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 31ae60add2..06e907a6d2 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -527,6 +527,13 @@ 基本情報 チェーン コントラクトアドレス + スタブ + スタブ + スタブ + スタブ + スタブ + スタブ + スタブ 最終販売価格 レアリティ・ラベル レアリティ・ランク @@ -1044,7 +1051,7 @@ バリデーター: %s 最小%s 最小取引金額は%1$sです。 - Tronネットワークの人気トークンの手数料は高めです。TRXをステーキングすると、より安く、あるいは無料で取引できます。 + Tronネットワークの人気トークンの手数料は高い可能性があります。TRXをステーキングすると、取引コストを削減できる可能性があります。 Tronネットワーク手数料を節約 もう一度やり直してください 同じカードをスキャンしました。ツインウォレットを作成するには、番号%dのカードをスキャンする必要があります。 @@ -1237,6 +1244,7 @@ 検証済みドメイン Tangemアプリで誤ったカードまたはリングが選択されました 問題が起きています + アドレス 接続する ネットワーク ネットワーク @@ -1249,6 +1257,8 @@ したい 接続リクエスト 接続 + 内容 + データをコピー すべての接続を解除する すべてのdAppsの接続解除に関するテキスト すべてのdAppを接続解除する @@ -1259,6 +1269,11 @@ セッションなし このドメインは複数のセキュリティプロバイダーから安全でないとの警告を受けています。あなたの資産を守るため、直ちにアクセスを中止してください。 既知のセキュリティリスク + リクエスト元 + 署名タイプ + 宛先 + 取引リクエスト + 取引リクエスト ウォレットコネクト 破棄 バックアップが中断されました。再開しますか? diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 5c2ba817f3..e43530482d 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -1305,6 +1305,7 @@ Verified domain Wrong card or ring selected in Tangem App We\'ve got some kind of problem + Address Connect Network Networks @@ -1331,6 +1332,7 @@ Known security risk Request from Signature Type + To Transaction request Transaction request Wallet connect diff --git a/core/ui/src/main/res/drawable/ic_fee_new_24.xml b/core/ui/src/main/res/drawable/ic_fee_new_24.xml new file mode 100644 index 0000000000..a644c488cf --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_fee_new_24.xml @@ -0,0 +1,21 @@ + + + + + + diff --git a/core/ui/src/main/res/drawable/ic_user_square_24.xml b/core/ui/src/main/res/drawable/ic_user_square_24.xml new file mode 100644 index 0000000000..655ae700f5 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_user_square_24.xml @@ -0,0 +1,17 @@ + + + + + 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 8d43fc1ebe..84a40f03e0 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 @@ -42,6 +42,7 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) +@Suppress("TooManyFunctions") internal object WalletConnectDataModule { @Provides @@ -86,6 +87,7 @@ internal object WalletConnectDataModule { dispatchers: CoroutineDispatcherProvider, legacyStore: WalletConnectSessionsRepository, getWallets: GetWalletsUseCase, + associateNetworks: AssociateNetworksDelegate, ): DefaultWcSessionsManager { val scope = CoroutineScope(SupervisorJob() + dispatchers.io) return DefaultWcSessionsManager( @@ -93,6 +95,7 @@ internal object WalletConnectDataModule { dispatchers = dispatchers, legacyStore = legacyStore, getWallets = getWallets, + associateNetworks = associateNetworks, scope = scope, ) } @@ -121,12 +124,12 @@ internal object WalletConnectDataModule { @Singleton fun wcEthNetwork( @SdkMoshi moshi: Moshi, - excludedBlockchains: ExcludedBlockchains, sessionsManager: WcSessionsManager, factories: WcEthNetwork.Factories, + namespaceConverter: WcEthNetwork.NamespaceConverter, ): WcEthNetwork = WcEthNetwork( moshi = moshi, - excludedBlockchains = excludedBlockchains, + namespaceConverter = namespaceConverter, sessionsManager = sessionsManager, factories = factories, ) @@ -135,7 +138,7 @@ internal object WalletConnectDataModule { @Singleton fun wcSolanaNetwork( @SdkMoshi moshi: Moshi, - excludedBlockchains: ExcludedBlockchains, + namespaceConverter: WcSolanaNetwork.NamespaceConverter, sessionsManager: WcSessionsManager, factories: WcSolanaNetwork.Factories, walletManager: UserWalletManager, @@ -143,28 +146,28 @@ internal object WalletConnectDataModule { moshi = moshi, sessionsManager = sessionsManager, factories = factories, - excludedBlockchains = excludedBlockchains, + namespaceConverter = namespaceConverter, walletManager = walletManager, ) @Provides @Singleton fun caipNamespaceDelegate( - diHelperBox: DiHelperBox, + namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>, walletManagersFacade: WalletManagersFacade, ): CaipNamespaceDelegate = CaipNamespaceDelegate( - namespaceConverters = diHelperBox.converters, + namespaceConverters = namespaceConverters, walletManagersFacade = walletManagersFacade, ) @Provides @Singleton fun associateNetworksDelegate( - diHelperBox: DiHelperBox, + namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>, getWallets: GetWalletsUseCase, currenciesRepository: CurrenciesRepository, ): AssociateNetworksDelegate = AssociateNetworksDelegate( - namespaceConverters = diHelperBox.converters, + namespaceConverters = namespaceConverters, getWallets = getWallets, currenciesRepository = currenciesRepository, ) @@ -176,10 +179,16 @@ internal object WalletConnectDataModule { ethNetwork, solanaNetwork, ), - converters = setOf( - ethNetwork, - solanaNetwork, - ), + ) + + @Provides + @Singleton + fun namespaceConverters( + ethNamespaceConverter: WcEthNetwork.NamespaceConverter, + solanaNamespaceConverter: WcSolanaNetwork.NamespaceConverter, + ): Set<@JvmSuppressWildcards WcNamespaceConverter> = setOf( + ethNamespaceConverter, + solanaNamespaceConverter, ) @Provides @@ -188,6 +197,20 @@ internal object WalletConnectDataModule { return DefaultWcRequestUseCaseFactory(diHelperBox.handlers) } + @Provides + @Singleton + fun wcEthNetworkNamespaceConverter(excludedBlockchains: ExcludedBlockchains): WcEthNetwork.NamespaceConverter { + return WcEthNetwork.NamespaceConverter(excludedBlockchains) + } + + @Provides + @Singleton + fun wcSolanaNetworkNamespaceConverter( + excludedBlockchains: ExcludedBlockchains, + ): WcSolanaNetwork.NamespaceConverter { + return WcSolanaNetwork.NamespaceConverter(excludedBlockchains) + } + @Provides @Singleton fun providesWcDisconnectUseCase(sessionsManager: WcSessionsManager): WcDisconnectUseCase { @@ -195,7 +218,6 @@ internal object WalletConnectDataModule { } internal class DiHelperBox( - val converters: Set, val handlers: Set, ) } \ No newline at end of file diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt index 175f715409..5dda26b898 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt @@ -22,12 +22,10 @@ import jakarta.inject.Inject internal class WcEthNetwork( private val moshi: Moshi, - private val excludedBlockchains: ExcludedBlockchains, private val sessionsManager: WcSessionsManager, private val factories: Factories, -) : WcRequestToUseCaseConverter, WcNamespaceConverter { - - override val namespaceKey: NamespaceKey = NamespaceKey("eip155") + private val namespaceConverter: NamespaceConverter, +) : WcRequestToUseCaseConverter { override fun toWcMethodName(request: WcSdkSessionRequest): WcEthMethodName? { val methodKey = request.request.method @@ -39,7 +37,7 @@ internal class WcEthNetwork( val name = toWcMethodName(request) ?: return null val method: WcEthMethod = name.toMethod(request) ?: return null val session = sessionsManager.findSessionByTopic(request.topic) ?: return null - val network = toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null + val network = namespaceConverter.toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null val accountAddress = when (method) { is WcEthMethod.MessageSign -> method.account is WcEthMethod.SendTransaction -> method.transaction.from @@ -100,24 +98,31 @@ internal class WcEthNetwork( return WcEthMethod.SignTypedData(params = params, account = account, dataForSign = data) } - override fun toNetwork(chainId: String, wallet: UserWallet): Network? { - return toNetwork(chainId, wallet, excludedBlockchains) - } + internal class NamespaceConverter constructor( + private val excludedBlockchains: ExcludedBlockchains, + ) : WcNamespaceConverter { - override fun toBlockchain(chainId: CAIP2): Blockchain? { - if (chainId.namespace != namespaceKey.key) return null - val ethChainId = chainId.reference.toIntOrNull() ?: return null - return Blockchain.fromChainId(ethChainId) - } + override val namespaceKey: NamespaceKey = NamespaceKey("eip155") - override fun toCAIP2(network: Network): CAIP2? { - val blockchain = Blockchain.fromId(network.id.value) - if (!blockchain.isEvm()) return null - val chainId = blockchain.getChainId() ?: return null - return CAIP2( - namespace = namespaceKey.key, - reference = chainId.toString(), - ) + override fun toNetwork(chainId: String, wallet: UserWallet): Network? { + return toNetwork(chainId, wallet, excludedBlockchains) + } + + override fun toBlockchain(chainId: CAIP2): Blockchain? { + if (chainId.namespace != namespaceKey.key) return null + val ethChainId = chainId.reference.toIntOrNull() ?: return null + return Blockchain.fromChainId(ethChainId) + } + + override fun toCAIP2(network: Network): CAIP2? { + val blockchain = Blockchain.fromId(network.id.value) + if (!blockchain.isEvm()) return null + val chainId = blockchain.getChainId() ?: return null + return CAIP2( + namespace = namespaceKey.key, + reference = chainId.toString(), + ) + } } internal class Factories @Inject constructor( diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt index 275c995ecf..21cc7cb152 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt @@ -26,11 +26,9 @@ internal class WcSolanaNetwork( private val moshi: Moshi, private val sessionsManager: WcSessionsManager, private val factories: Factories, - private val excludedBlockchains: ExcludedBlockchains, + private val namespaceConverter: NamespaceConverter, private val walletManager: UserWalletManager, -) : WcNamespaceConverter, WcRequestToUseCaseConverter { - - override val namespaceKey: NamespaceKey = NamespaceKey("solana") +) : WcRequestToUseCaseConverter { override fun toWcMethodName(request: WcSdkSessionRequest): WcSolanaMethodName? { val methodKey = request.request.method @@ -42,7 +40,7 @@ internal class WcSolanaNetwork( val name = toWcMethodName(request) ?: return null val method: WcSolanaMethod = name.toMethod(request) ?: return null val session = sessionsManager.findSessionByTopic(request.topic) ?: return null - val network = toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null + val network = namespaceConverter.toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null val accountAddress = getAccountAddress(network) val context = WcMethodUseCaseContext( session = session, @@ -66,31 +64,38 @@ internal class WcSolanaNetwork( } } - override fun toBlockchain(chainId: CAIP2): Blockchain? { - if (chainId.namespace != namespaceKey.key) return null - return when (chainId.reference) { - MAINNET_CHAIN_ID -> Blockchain.Solana - TESTNET_CHAIN_ID -> Blockchain.SolanaTestnet - else -> null - } - } + internal class NamespaceConverter @Inject constructor( + private val excludedBlockchains: ExcludedBlockchains, + ) : WcNamespaceConverter { - override fun toNetwork(chainId: String, wallet: UserWallet): Network? { - return toNetwork(chainId, wallet, excludedBlockchains) - } + override val namespaceKey: NamespaceKey = NamespaceKey("solana") - override fun toCAIP2(network: Network): CAIP2? { - val blockchain = Blockchain.fromId(network.id.value) - val chainId = when (blockchain) { - Blockchain.Solana -> MAINNET_CHAIN_ID - Blockchain.SolanaTestnet -> TESTNET_CHAIN_ID - else -> null + override fun toBlockchain(chainId: CAIP2): Blockchain? { + if (chainId.namespace != namespaceKey.key) return null + return when (chainId.reference) { + MAINNET_CHAIN_ID -> Blockchain.Solana + TESTNET_CHAIN_ID -> Blockchain.SolanaTestnet + else -> null + } + } + + override fun toNetwork(chainId: String, wallet: UserWallet): Network? { + return toNetwork(chainId, wallet, excludedBlockchains) + } + + override fun toCAIP2(network: Network): CAIP2? { + val blockchain = Blockchain.fromId(network.id.value) + val chainId = when (blockchain) { + Blockchain.Solana -> MAINNET_CHAIN_ID + Blockchain.SolanaTestnet -> TESTNET_CHAIN_ID + else -> null + } + chainId ?: return null + return CAIP2( + namespace = namespaceKey.key, + reference = chainId, + ) } - chainId ?: return null - return CAIP2( - namespace = namespaceKey.key, - reference = chainId, - ) } private fun WcSolanaMethodName.toMethod(request: WcSdkSessionRequest): WcSolanaMethod? { diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt index 15ffca4caf..04906abf44 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt @@ -1,6 +1,7 @@ package com.tangem.data.walletconnect.pair import com.reown.walletkit.client.Wallet +import com.reown.walletkit.client.Wallet.Model.Namespace import com.tangem.data.walletconnect.utils.WcNamespaceConverter import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network @@ -16,6 +17,16 @@ internal class AssociateNetworksDelegate constructor( private val currenciesRepository: CurrenciesRepository, ) { + suspend fun associate(wallet: UserWallet, namespaces: Map): Set { + val walletNetworks = getWalletNetworks(wallet) + val namespacesSet = namespaces.values.flatMap { proposal -> proposal.chains ?: listOf() }.toSet() + return namespacesSet.mapNotNullTo(mutableSetOf()) { chainId -> + val wcNetwork = namespaceConverters + .firstNotNullOfOrNull { it.toNetwork(chainId, wallet) } ?: return@mapNotNullTo null + walletNetworks.find { network -> wcNetwork.id == network.id } + } + } + @Throws(WcPairError.UnsupportedNetworks::class) suspend fun associate(sessionProposal: Wallet.Model.SessionProposal): Map { val userWallets = getWallets.invokeSync().filter { it.isMultiCurrency } @@ -31,9 +42,7 @@ internal class AssociateNetworksDelegate constructor( requiredNamespaces: Set, optionalNamespaces: Set, ): ProposalNetwork { - val walletNetworks = currenciesRepository.getMultiCurrencyWalletCurrenciesSync(wallet.walletId) - .filterIsInstance() - .map { it.network } + val walletNetworks = getWalletNetworks(wallet) val unknownRequired = mutableSetOf() val missingRequired = mutableSetOf() @@ -74,6 +83,11 @@ internal class AssociateNetworksDelegate constructor( ) } + private suspend fun getWalletNetworks(wallet: UserWallet): List = + currenciesRepository.getMultiCurrencyWalletCurrenciesSync(wallet.walletId) + .filterIsInstance() + .map { it.network } + private fun Map.setOfChainId(): Set = this.values.flatMap { proposal -> proposal.chains ?: listOf() }.toSet() diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt index fc91e5eefe..5bcbce241a 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt @@ -14,7 +14,6 @@ import com.tangem.domain.walletconnect.model.sdkcopy.WcAppMetaData import com.tangem.domain.walletconnect.repository.WcSessionsManager import com.tangem.domain.walletconnect.usecase.pair.WcPairState import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase -import com.tangem.domain.wallets.models.UserWallet import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -78,9 +77,11 @@ internal class DefaultWcPairUseCase @AssistedInject constructor( sessionForApprove = sessionForApprove, sdkSessionProposal = sdkSessionProposal, ).map { settledSession -> - val newSession = settledSession.session.toDomain( + val newSession = WcSession( wallet = sessionForApprove.wallet, + sdkModel = WcSdkSessionConverter.convert(settledSession.session), securityStatus = proposalState.dAppSession.securityStatus, + networks = sessionForApprove.network.toSet(), ) sessionsManager.saveSession(newSession) newSession @@ -141,14 +142,6 @@ internal class DefaultWcPairUseCase @AssistedInject constructor( } },) - private fun Wallet.Model.Session.toDomain(wallet: UserWallet, securityStatus: CheckDAppResult): WcSession { - return WcSession( - wallet = wallet, - sdkModel = WcSdkSessionConverter.convert(this), - securityStatus = securityStatus, - ) - } - private sealed interface TerminalAction { data class Approve(val sessionForApprove: WcSessionApprove) : TerminalAction data object Reject : TerminalAction 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 98e554f3fe..1c537ef70d 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 @@ -6,6 +6,7 @@ import arrow.core.right import com.domain.blockaid.models.dapp.CheckDAppResult import com.reown.walletkit.client.Wallet import com.reown.walletkit.client.WalletKit +import com.tangem.data.walletconnect.pair.AssociateNetworksDelegate import com.tangem.data.walletconnect.utils.WcSdkObserver import com.tangem.data.walletconnect.utils.WcSdkSessionConverter import com.tangem.datasource.local.walletconnect.WalletConnectStore @@ -29,6 +30,7 @@ internal class DefaultWcSessionsManager( private val legacyStore: WalletConnectSessionsRepository, private val getWallets: GetWalletsUseCase, private val dispatchers: CoroutineDispatcherProvider, + private val associateNetworks: AssociateNetworksDelegate, private val scope: CoroutineScope, ) : WcSessionsManager, WcSdkObserver { @@ -76,10 +78,12 @@ internal class DefaultWcSessionsManager( ?: return@withContext null val sdkSession = WalletKit.getActiveSessionByTopic(topic) ?: return@withContext null val wallet = storedSession.wallet + val networks = associateNetworks.associate(wallet, sdkSession.namespaces) WcSession( wallet = wallet, sdkModel = WcSdkSessionConverter.convert(sdkSession), securityStatus = storedSession.securityStatus, + networks = networks, ) } @@ -114,7 +118,7 @@ internal class DefaultWcSessionsManager( return mustSaveInNewStore.isNotEmpty() } - private fun associate( + private suspend fun associate( inSdk: List, inStore: Set, wallets: List, @@ -122,7 +126,13 @@ internal class DefaultWcSessionsManager( val wcSessions = inStore.mapNotNull { session -> val wallet = wallets.find { it.walletId == session.walletId } ?: return@mapNotNull null val sdkSession = inSdk.find { it.topic == session.topic } ?: return@mapNotNull null - WcSession(wallet = wallet, sdkModel = WcSdkSessionConverter.convert(sdkSession), session.securityStatus) + val networks = associateNetworks.associate(wallet, sdkSession.namespaces) + WcSession( + wallet = wallet, + sdkModel = WcSdkSessionConverter.convert(sdkSession), + securityStatus = session.securityStatus, + networks = networks, + ) } return wcSessions } diff --git a/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/DefaultWcPairUseCaseTest.kt b/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/DefaultWcPairUseCaseTest.kt index 1792340585..6a86ee96f2 100644 --- a/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/DefaultWcPairUseCaseTest.kt +++ b/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/DefaultWcPairUseCaseTest.kt @@ -20,6 +20,7 @@ import com.tangem.domain.walletconnect.model.WcSession import com.tangem.domain.walletconnect.model.WcSessionApprove import com.tangem.domain.walletconnect.repository.WcSessionsManager import com.tangem.domain.walletconnect.usecase.pair.WcPairState +import com.tangem.domain.wallets.models.UserWalletId import io.mockk.coEvery import io.mockk.coVerifyOrder import io.mockk.mockk @@ -91,6 +92,7 @@ internal class DefaultWcPairUseCaseTest { wallet = sessionForApprove.wallet, sdkModel = WcSdkSessionConverter.convert(this), securityStatus = CheckDAppResult.SAFE, + networks = setOf(), ) private fun useCaseFactory() = DefaultWcPairUseCase( @@ -99,7 +101,7 @@ internal class DefaultWcPairUseCaseTest { caipNamespaceDelegate = caipNamespaceDelegate, sdkDelegate = sdkDelegate, blockAidVerifier = blockAidVerifier, - pairRequest = WcPairRequest(url, source), + pairRequest = WcPairRequest(userWalletId = UserWalletId(""), uri = url, source = source), ) @Before diff --git a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt index 0c83963864..29cddff1c0 100644 --- a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt +++ b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt @@ -14,7 +14,6 @@ import com.tangem.domain.tokens.TokensFeatureToggles import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.tokens.repository.QuotesRepository import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.models.UserWalletId @@ -24,7 +23,6 @@ class SaveManagedTokensUseCase( private val customTokensRepository: CustomTokensRepository, private val walletManagersFacade: WalletManagersFacade, private val currenciesRepository: CurrenciesRepository, - private val networksRepository: NetworksRepository, private val derivationsRepository: DerivationsRepository, private val stakingRepository: StakingRepository, private val quotesRepository: QuotesRepository, @@ -102,20 +100,12 @@ class SaveManagedTokensUseCase( val networkToUpdate = currenciesToAdd.map { it.network } .subtract(existingCurrencies.map { it.network }.toSet()) - if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - multiNetworkStatusFetcher( - MultiNetworkStatusFetcher.Params( - userWalletId = userWalletId, - networks = networksToUpdate + networkToUpdate, - ), - ) - } else { - networksRepository.getNetworkStatusesSync( + multiNetworkStatusFetcher( + MultiNetworkStatusFetcher.Params( userWalletId = userWalletId, networks = networksToUpdate + networkToUpdate, - refresh = true, - ) - } + ), + ) } private suspend fun refreshUpdatedYieldBalances( diff --git a/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt b/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt index 1d0215f044..cbc09a8700 100644 --- a/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt +++ b/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt @@ -12,7 +12,6 @@ import com.tangem.domain.tokens.TokensFeatureToggles import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.tokens.repository.QuotesRepository import com.tangem.domain.wallets.models.UserWalletId @@ -30,7 +29,6 @@ class SaveMarketTokensUseCase( private val derivationsRepository: DerivationsRepository, private val marketsTokenRepository: MarketsTokenRepository, private val currenciesRepository: CurrenciesRepository, - private val networksRepository: NetworksRepository, private val stakingRepository: StakingRepository, private val quotesRepository: QuotesRepository, private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher, @@ -83,20 +81,12 @@ class SaveMarketTokensUseCase( } private suspend fun refreshUpdatedNetworks(userWalletId: UserWalletId, addedCurrencies: List) { - if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - multiNetworkStatusFetcher( - MultiNetworkStatusFetcher.Params( - userWalletId = userWalletId, - networks = addedCurrencies.map(CryptoCurrency::network).toSet(), - ), - ) - } else { - networksRepository.getNetworkStatusesSync( + multiNetworkStatusFetcher( + MultiNetworkStatusFetcher.Params( userWalletId = userWalletId, networks = addedCurrencies.map(CryptoCurrency::network).toSet(), - refresh = true, - ) - } + ), + ) } private suspend fun refreshUpdatedYieldBalances( diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt index 721fbd04da..97f3acfd0d 100644 --- a/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt @@ -8,9 +8,9 @@ import com.tangem.common.card.EllipticCurve import com.tangem.common.card.EncryptionMode import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey +import com.tangem.common.card.FirmwareVersion as SdkFirmwareVersion import com.tangem.operations.attestation.Attestation import java.util.Date -import com.tangem.common.card.FirmwareVersion as SdkFirmwareVersion // TODO: Move to :domain:card:models /** @@ -189,6 +189,8 @@ data class CardDTO( minor != other.minor -> minor.compareTo(other.minor) else -> patch.compareTo(other.patch) } + + fun toSdkFirmwareVersion() = SdkFirmwareVersion(major = major, minor = minor) } @JsonClass(generateAdapter = true) diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt index ca0fecd294..a8bb9a147e 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt @@ -12,7 +12,6 @@ import com.tangem.domain.staking.single.SingleYieldBalanceFetcher import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.tokens.repository.QuotesRepository import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.async @@ -29,7 +28,6 @@ import kotlinx.coroutines.coroutineScope @Suppress("LongParameterList") class AddCryptoCurrenciesUseCase( private val currenciesRepository: CurrenciesRepository, - private val networksRepository: NetworksRepository, private val stakingRepository: StakingRepository, private val quotesRepository: QuotesRepository, private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher, @@ -139,26 +137,13 @@ class AddCryptoCurrenciesUseCase( } ?.network - if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - multiNetworkStatusFetcher( - MultiNetworkStatusFetcher.Params( - userWalletId = userWalletId, - networks = setOfNotNull(networksToUpdate, networkToUpdate), - ), - ) - } else { - catch( - { - networksRepository.getNetworkStatusesSync( - userWalletId = userWalletId, - networks = setOfNotNull(networksToUpdate, networkToUpdate), - refresh = true, - ) - }, - ) { - raise(it) - } - } + multiNetworkStatusFetcher( + MultiNetworkStatusFetcher.Params( + userWalletId = userWalletId, + networks = setOfNotNull(networksToUpdate, networkToUpdate), + ), + ) + .bind() } private suspend fun refreshUpdatedYieldBalances(userWalletId: UserWalletId, addedCurrency: CryptoCurrency) { diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCardTokenListUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCardTokenListUseCase.kt index 7d56e24a4b..1019ef739e 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCardTokenListUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCardTokenListUseCase.kt @@ -13,7 +13,6 @@ import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.tokens.repository.QuotesRepository import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.async @@ -23,7 +22,6 @@ import kotlinx.coroutines.coroutineScope @Suppress("LongParameterList") class FetchCardTokenListUseCase( private val currenciesRepository: CurrenciesRepository, - private val networksRepository: NetworksRepository, private val quotesRepository: QuotesRepository, private val stakingRepository: StakingRepository, private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher, @@ -41,7 +39,6 @@ class FetchCardTokenListUseCase( fetchNetworksStatuses( userWalletId = userWalletId, networks = currencies.mapTo(destination = hashSetOf(), transform = CryptoCurrency::network), - refresh = refresh, ) } val fetchQuotes = async { @@ -80,19 +77,12 @@ class FetchCardTokenListUseCase( private suspend fun Raise.fetchNetworksStatuses( userWalletId: UserWalletId, networks: Set, - refresh: Boolean, ) { - if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - multiNetworkStatusFetcher( - MultiNetworkStatusFetcher.Params(userWalletId = userWalletId, networks = networks), - ) - .mapLeft { TokenListError.DataError(it) } - } else { - catch( - block = { networksRepository.getNetworkStatusesSync(userWalletId, networks, refresh) }, - catch = { raise(TokenListError.DataError(it)) }, - ) - } + multiNetworkStatusFetcher( + MultiNetworkStatusFetcher.Params(userWalletId = userWalletId, networks = networks), + ) + .mapLeft(TokenListError::DataError) + .bind() } private suspend fun fetchQuotes(currenciesIds: Set, refresh: Boolean) { diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt index e9775c5d32..dee7078730 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt @@ -13,7 +13,6 @@ import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.tokens.repository.QuotesRepository import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.async @@ -26,14 +25,12 @@ import kotlinx.coroutines.coroutineScope * by providing a specific currency ID or fetching the status of the primary currency. * * @param currenciesRepository The repository for retrieving currency-related data. - * @param networksRepository The repository for retrieving network-related data. * @param quotesRepository The repository for retrieving cryptocurrency quotes. */ // TODO: Add tests @Suppress("LongParameterList") class FetchCurrencyStatusUseCase( private val currenciesRepository: CurrenciesRepository, - private val networksRepository: NetworksRepository, private val quotesRepository: QuotesRepository, private val stakingRepository: StakingRepository, private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher, @@ -86,7 +83,7 @@ class FetchCurrencyStatusUseCase( refresh: Boolean, ) = coroutineScope { val fetchStatus = async { - fetchNetworkStatus(userWalletId, currency.network, refresh) + fetchNetworkStatus(userWalletId, currency.network) } val fetchQuote = async { fetchQuote(currency.id, refresh) @@ -120,23 +117,12 @@ class FetchCurrencyStatusUseCase( } } - private suspend fun Raise.fetchNetworkStatus( - userWalletId: UserWalletId, - network: Network, - refresh: Boolean, - ) { - if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - singleNetworkStatusFetcher( - params = SingleNetworkStatusFetcher.Params(userWalletId = userWalletId, network = network), - ) - .mapLeft { CurrencyStatusError.DataError(it) } - } else { - catch( - block = { networksRepository.getNetworkStatusesSync(userWalletId, setOf(network), refresh) }, - ) { - raise(CurrencyStatusError.DataError(it)) - } - } + private suspend fun Raise.fetchNetworkStatus(userWalletId: UserWalletId, network: Network) { + singleNetworkStatusFetcher( + params = SingleNetworkStatusFetcher.Params(userWalletId = userWalletId, network = network), + ) + .mapLeft { CurrencyStatusError.DataError(it) } + .bind() } private suspend fun Raise.fetchQuote(currencyId: CryptoCurrency.ID, refresh: Boolean) { diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchTokenListUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchTokenListUseCase.kt index e0300eb83a..3061b1152d 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchTokenListUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchTokenListUseCase.kt @@ -15,7 +15,6 @@ import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.tokens.repository.QuotesRepository import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.async @@ -27,7 +26,6 @@ import kotlinx.coroutines.coroutineScope * network statuses, and quotes for tokens associated with a user's wallet. * * @param currenciesRepository The repository for retrieving currency-related data. - * @param networksRepository The repository for retrieving network-related data. * @param quotesRepository The repository for retrieving cryptocurrency quotes. * @param stakingRepository The repository for retrieving staking-related data. */ @@ -35,7 +33,6 @@ import kotlinx.coroutines.coroutineScope @Suppress("LongParameterList") class FetchTokenListUseCase( private val currenciesRepository: CurrenciesRepository, - private val networksRepository: NetworksRepository, private val quotesRepository: QuotesRepository, private val stakingRepository: StakingRepository, private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher, @@ -71,7 +68,6 @@ class FetchTokenListUseCase( fetchNetworksStatuses( userWalletId = userWalletId, networks = currencies.mapTo(hashSetOf()) { it.network }, - refresh = mode.refreshNetworksStatuses, ) } val fetchQuotes = async { @@ -111,23 +107,12 @@ class FetchTokenListUseCase( private suspend fun Raise.fetchNetworksStatuses( userWalletId: UserWalletId, networks: Set, - refresh: Boolean, ) { - if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - if (refresh) { - multiNetworkStatusFetcher( - params = MultiNetworkStatusFetcher.Params(userWalletId, networks), - ) - .mapLeft { TokenListError.DataError(it) } - .bind() - } - } else { - catch( - block = { networksRepository.getNetworkStatusesSync(userWalletId, networks, refresh) }, - ) { - raise(TokenListError.DataError(it)) - } - } + multiNetworkStatusFetcher( + params = MultiNetworkStatusFetcher.Params(userWalletId = userWalletId, networks = networks), + ) + .mapLeft(TokenListError::DataError) + .bind() } private suspend fun fetchQuotes(currenciesIds: Set, refresh: Boolean) { @@ -175,25 +160,21 @@ class FetchTokenListUseCase( */ enum class RefreshMode( internal val refreshCurrencies: Boolean, - internal val refreshNetworksStatuses: Boolean, internal val refreshQuotes: Boolean, internal val refreshYieldBalances: Boolean, ) { NONE( refreshCurrencies = false, - refreshNetworksStatuses = false, refreshQuotes = false, refreshYieldBalances = false, ), FULL( refreshCurrencies = true, - refreshNetworksStatuses = true, refreshQuotes = true, refreshYieldBalances = true, ), SKIP_CURRENCIES( refreshCurrencies = false, - refreshNetworksStatuses = true, refreshQuotes = true, refreshYieldBalances = true, ), diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyStatusSyncUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyStatusSyncUseCase.kt deleted file mode 100644 index 20354b45c4..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyStatusSyncUseCase.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import com.tangem.domain.tokens.error.CurrencyStatusError -import com.tangem.domain.tokens.error.mapper.mapToCurrencyError -import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.domain.tokens.model.CryptoCurrencyStatus -import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations -import com.tangem.domain.wallets.models.UserWalletId - -class GetCryptoCurrencyStatusSyncUseCase( - private val currencyStatusOperations: BaseCurrencyStatusOperations, -) { - - // multi-currency - suspend operator fun invoke( - userWalletId: UserWalletId, - cryptoCurrencyId: CryptoCurrency.ID, - isSingleWalletWithTokens: Boolean = false, - ): Either { - return currencyStatusOperations.getCurrencyStatusSync(userWalletId, cryptoCurrencyId, isSingleWalletWithTokens) - .mapLeft { error -> error.mapToCurrencyError() } - } - - // single-currency - suspend operator fun invoke(userWalletId: UserWalletId): Either { - return currencyStatusOperations.getPrimaryCurrencyStatusSync(userWalletId) - .mapLeft { error -> error.mapToCurrencyError() } - } -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyStatusUpdatesUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyStatusUpdatesUseCase.kt deleted file mode 100644 index 0595b091fe..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyStatusUpdatesUseCase.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import com.tangem.domain.tokens.error.CurrencyStatusError -import com.tangem.domain.tokens.error.mapper.mapToCurrencyError -import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.domain.tokens.model.CryptoCurrencyStatus -import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations -import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.flow.* - -/** - * Use case for fetching the status of a cryptocurrency associated with a user wallet. - * - */ -class GetCurrencyStatusUpdatesUseCase( - private val currencyStatusOperations: BaseCurrencyStatusOperations, - private val dispatchers: CoroutineDispatcherProvider, -) { - - /** - * Invokes the use case. - * - * @param userWalletId The unique identifier of the user's wallet. - * @param currencyId The unique identifier of the cryptocurrency. - * @param isSingleWalletWithTokens Indicates whether the user wallet contains only one token on card (old cards) - * @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation. - */ - operator fun invoke( - userWalletId: UserWalletId, - currencyId: CryptoCurrency.ID, - isSingleWalletWithTokens: Boolean, - ): Flow> { - return flow { - emitAll( - getCurrencyStatus( - userWalletId = userWalletId, - currencyId = currencyId, - isSingleWalletWithTokens = isSingleWalletWithTokens, - ), - ) - }.flowOn(dispatchers.io) - } - - private suspend fun getCurrencyStatus( - userWalletId: UserWalletId, - currencyId: CryptoCurrency.ID, - isSingleWalletWithTokens: Boolean, - ): Flow> { - val currencyFlow = currencyStatusOperations.getCurrencyStatusFlow( - userWalletId = userWalletId, - currencyId = currencyId, - isSingleWalletWithTokens = isSingleWalletWithTokens, - ) - - return currencyFlow.map { maybeCurrency -> - maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError) - } - } -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyStatusesSyncUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetMultiCryptoCurrencyStatusUseCase.kt similarity index 50% rename from domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyStatusesSyncUseCase.kt rename to domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetMultiCryptoCurrencyStatusUseCase.kt index 590cb6caa0..56b50913c1 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyStatusesSyncUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetMultiCryptoCurrencyStatusUseCase.kt @@ -1,17 +1,25 @@ package com.tangem.domain.tokens import arrow.core.Either +import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.tokens.error.mapper.mapToTokenListError import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations import com.tangem.domain.wallets.models.UserWalletId +import kotlinx.coroutines.flow.Flow -class GetCryptoCurrencyStatusesSyncUseCase( +class GetMultiCryptoCurrencyStatusUseCase( private val currencyStatusOperations: BaseCurrencyStatusOperations, ) { - suspend operator fun invoke(userWalletId: UserWalletId): Either> { + /** + * Returns synchronously list of cryptocurrency statuses for Multi-Currency wallet + * + * @param userWalletId The unique identifier of the user's wallet. + * @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation. + */ + suspend fun invokeMultiWalletSync(userWalletId: UserWalletId): Either> { return currencyStatusOperations.getCurrenciesStatusesSync(userWalletId) .mapLeft { error -> error.mapToTokenListError() } } diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCase.kt deleted file mode 100644 index 000411bff6..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCase.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import com.tangem.domain.tokens.error.CurrencyStatusError -import com.tangem.domain.tokens.error.mapper.mapToCurrencyError -import com.tangem.domain.tokens.model.CryptoCurrencyStatus -import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations -import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.flow.* - -/** - * Use case for fetching the status of the primary cryptocurrency associated with a user wallet. - * - * @property dispatchers Provides coroutine dispatchers. - */ -class GetPrimaryCurrencyStatusUpdatesUseCase( - private val dispatchers: CoroutineDispatcherProvider, - private val currencyStatusOperations: BaseCurrencyStatusOperations, -) { - - /** - * Invokes the use case. - * - * @param userWalletId The unique identifier of the user's wallet. - * @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation. - */ - operator fun invoke(userWalletId: UserWalletId): Flow> { - return flow { - emitAll(getPrimaryCurrency(userWalletId)) - }.flowOn(dispatchers.io) - } - - private suspend fun getPrimaryCurrency( - userWalletId: UserWalletId, - ): Flow> { - return currencyStatusOperations.getPrimaryCurrencyStatusFlow(userWalletId).map { maybeCurrency -> - maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError) - } - } -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetSingleCryptoCurrencyStatusUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetSingleCryptoCurrencyStatusUseCase.kt new file mode 100644 index 0000000000..928221f31b --- /dev/null +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetSingleCryptoCurrencyStatusUseCase.kt @@ -0,0 +1,106 @@ +package com.tangem.domain.tokens + +import arrow.core.Either +import com.tangem.domain.tokens.error.CurrencyStatusError +import com.tangem.domain.tokens.error.mapper.mapToCurrencyError +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations +import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations +import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.flow.* + +/** + * Use case for fetching the status of a cryptocurrency associated with a user wallet. + * + */ +class GetSingleCryptoCurrencyStatusUseCase( + private val currencyStatusOperations: BaseCurrencyStatusOperations, + private val dispatchers: CoroutineDispatcherProvider, +) { + + /** + * Returns cryptocurrency status flow for Multi-Currency wallet + * + * @param userWalletId The unique identifier of the user's wallet. + * @param currencyId The unique identifier of the cryptocurrency. + * @param isSingleWalletWithTokens Indicates whether the user wallet contains only one token on card (old cards) + * @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation. + */ + fun invokeMultiWallet( + userWalletId: UserWalletId, + currencyId: CryptoCurrency.ID, + isSingleWalletWithTokens: Boolean, + ): Flow> { + return flow { + emitAll( + getCurrencyStatus( + userWalletId = userWalletId, + currencyId = currencyId, + isSingleWalletWithTokens = isSingleWalletWithTokens, + ), + ) + }.flowOn(dispatchers.io) + } + + /** + * Returns cryptocurrency status flow for primary currency for Single-Currency wallet + * + * @param userWalletId The unique identifier of the user's wallet. + * @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation. + */ + fun invokeSingleWallet(userWalletId: UserWalletId): Flow> { + return flow { + emitAll( + currencyStatusOperations.getPrimaryCurrencyStatusFlow(userWalletId).map { maybeCurrency -> + maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError) + }, + ) + }.flowOn(dispatchers.io) + } + + /** + * Returns synchronously cryptocurrency status for Multi-Currency wallet + * + * @param userWalletId The unique identifier of the user's wallet. + * @param cryptoCurrencyId The unique identifier of the cryptocurrency. + * @param isSingleWalletWithTokens Indicates whether the user wallet contains only one token on card (old cards) + * @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation. + */ + suspend fun invokeMultiWalletSync( + userWalletId: UserWalletId, + cryptoCurrencyId: CryptoCurrency.ID, + isSingleWalletWithTokens: Boolean = false, + ): Either { + return currencyStatusOperations.getCurrencyStatusSync(userWalletId, cryptoCurrencyId, isSingleWalletWithTokens) + .mapLeft { error -> error.mapToCurrencyError() } + } + + /** + * Returns synchronously cryptocurrency status for primary currency for Single-Currency wallet + * + * @param userWalletId The unique identifier of the user's wallet. + * @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation. + */ + suspend fun invokeSingleWalletSync(userWalletId: UserWalletId): Either { + return currencyStatusOperations.getPrimaryCurrencyStatusSync(userWalletId) + .mapLeft { error -> error.mapToCurrencyError() } + } + + private suspend fun getCurrencyStatus( + userWalletId: UserWalletId, + currencyId: CryptoCurrency.ID, + isSingleWalletWithTokens: Boolean, + ): Flow> { + val currencyFlow = currencyStatusOperations.getCurrencyStatusFlow( + userWalletId = userWalletId, + currencyId = currencyId, + isSingleWalletWithTokens = isSingleWalletWithTokens, + ) + + return currencyFlow.map { maybeCurrency -> + maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError) + } + } +} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/TokensFeatureToggles.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/TokensFeatureToggles.kt index be40961b10..b969947239 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/TokensFeatureToggles.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/TokensFeatureToggles.kt @@ -7,8 +7,6 @@ package com.tangem.domain.tokens */ interface TokensFeatureToggles { - val isNetworksLoadingRefactoringEnabled: Boolean - val isQuotesLoadingRefactoringEnabled: Boolean val isStakingLoadingRefactoringEnabled: Boolean diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/UpdateDelayedNetworkStatusUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/UpdateDelayedNetworkStatusUseCase.kt index 5be8ae95ef..632b102018 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/UpdateDelayedNetworkStatusUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/UpdateDelayedNetworkStatusUseCase.kt @@ -2,12 +2,10 @@ package com.tangem.domain.tokens import arrow.core.Either import arrow.core.raise.Raise -import arrow.core.raise.catch import arrow.core.raise.either import com.tangem.domain.networks.single.SingleNetworkStatusFetcher import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.Network -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.delay @@ -15,14 +13,9 @@ import kotlinx.coroutines.delay * Use case responsible for fetching currency status information, including network status * and quotes for a given cryptocurrency. It provides methods to fetch currency status either * by providing a specific currency ID or fetching the status of the primary currency. - * - * @param networksRepository The repository for retrieving network-related data. */ - class UpdateDelayedNetworkStatusUseCase( - private val networksRepository: NetworksRepository, private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher, - private val tokensFeatureToggles: TokensFeatureToggles, ) { /** @@ -30,37 +23,24 @@ class UpdateDelayedNetworkStatusUseCase( * * @param userWalletId The ID of the user's wallet. * @param network Network of the cryptocurrency. - * @param refresh Indicates whether to force a refresh of the status data. * @return An [Either] representing success (Right) or an error (Left) in fetching the status. */ suspend operator fun invoke( userWalletId: UserWalletId, network: Network, delayMillis: Long = 0L, - refresh: Boolean = false, ): Either { delay(delayMillis) return either { - fetchNetworkStatus(userWalletId, network, refresh) + fetchNetworkStatus(userWalletId, network) } } - private suspend fun Raise.fetchNetworkStatus( - userWalletId: UserWalletId, - network: Network, - refresh: Boolean, - ) { - if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - singleNetworkStatusFetcher( - params = SingleNetworkStatusFetcher.Params(userWalletId = userWalletId, network = network), - ) - .mapLeft { CurrencyStatusError.DataError(it) } - } else { - catch( - block = { networksRepository.getNetworkStatusesSync(userWalletId, setOf(network), refresh) }, - ) { - raise(CurrencyStatusError.DataError(it)) - } - } + private suspend fun Raise.fetchNetworkStatus(userWalletId: UserWalletId, network: Network) { + singleNetworkStatusFetcher( + params = SingleNetworkStatusFetcher.Params(userWalletId = userWalletId, network = network), + ) + .mapLeft(CurrencyStatusError::DataError) + .bind() } } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/BaseCurrencyStatusOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/BaseCurrencyStatusOperations.kt index c2d41790de..b1d6b2f500 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/BaseCurrencyStatusOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/BaseCurrencyStatusOperations.kt @@ -22,7 +22,6 @@ import com.tangem.domain.tokens.TokensFeatureToggles import com.tangem.domain.tokens.model.* import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.tokens.repository.QuotesRepository import com.tangem.domain.tokens.utils.CurrencyStatusProxyCreator import com.tangem.domain.wallets.models.UserWalletId @@ -33,7 +32,6 @@ import kotlinx.coroutines.flow.* * * @property currenciesRepository repository for currencies * @property quotesRepository repository for quotes - * @property networksRepository repository for networks * @property stakingRepository repository for staking * [REDACTED_AUTHOR] @@ -43,7 +41,6 @@ abstract class BaseCurrencyStatusOperations( private val currenciesRepository: CurrenciesRepository, private val quotesRepository: QuotesRepository, private val quotesRepositoryV2: QuotesRepositoryV2, - private val networksRepository: NetworksRepository, private val stakingRepository: StakingRepository, private val multiNetworkStatusSupplier: MultiNetworkStatusSupplier, private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier, @@ -203,24 +200,14 @@ abstract class BaseCurrencyStatusOperations( ?.right() ?: Error.EmptyQuotes.left() - val networkStatuses = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - singleNetworkStatusSupplier( - params = SingleNetworkStatusProducer.Params( - userWalletId = userWalletId, - network = currency.network, - ), - ) - .firstOrNull() - .right() - } else { - networksRepository.getNetworkStatusesSync( + val networkStatuses = singleNetworkStatusSupplier( + params = SingleNetworkStatusProducer.Params( userWalletId = userWalletId, - networks = setOf(currency.network), - refresh = false, - ) - .firstOrNull { it.network == currency.network } - .right() - } + network = currency.network, + ), + ) + .firstOrNull() + .right() val yieldBalances = getYieldBalanceSync(userWalletId, currency) @@ -270,7 +257,7 @@ abstract class BaseCurrencyStatusOperations( val nonEmptyCurrencies = currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId).toNonEmptyListOrNull() ?: return emptyList().right() - val (networks, currenciesIds) = getIds(nonEmptyCurrencies) + val (_, currenciesIds) = getIds(nonEmptyCurrencies) val rawIds = currenciesIds.mapNotNull { it.rawCurrencyId }.toSet() val quotes = if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) { @@ -279,16 +266,13 @@ abstract class BaseCurrencyStatusOperations( quotesRepository.getQuotesSync(rawIds, false).right() } - val networkStatuses = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - multiNetworkStatusSupplier( - params = MultiNetworkStatusProducer.Params(userWalletId = userWalletId), - ) - .firstOrNull() - .orEmpty() - .right() - } else { - networksRepository.getNetworkStatusesSync(userWalletId, networks, false).right() - } + val networkStatuses = multiNetworkStatusSupplier( + params = MultiNetworkStatusProducer.Params(userWalletId = userWalletId), + ) + .firstOrNull() + .orEmpty() + .right() + val yieldBalances = getYieldBalancesSync(userWalletId, nonEmptyCurrencies) return currencyStatusProxyCreator.createCurrenciesStatuses( @@ -326,25 +310,11 @@ abstract class BaseCurrencyStatusOperations( ) } - val networkStatus = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - singleNetworkStatusSupplier( - params = SingleNetworkStatusProducer.Params( - userWalletId = userWalletId, - network = currency.network, - ), - ) - .firstOrNull() - .right() - } else { - catch( - block = { - networksRepository.getNetworkStatusesSync(userWalletId, setOf(currency.network)) - .firstOrNull { it.network == currency.network } - .right() - }, - catch = { Error.DataError(it).left() }, - ) - } + val networkStatus = singleNetworkStatusSupplier( + params = SingleNetworkStatusProducer.Params(userWalletId = userWalletId, network = currency.network), + ) + .firstOrNull() + .right() val yieldBalances = getYieldBalanceSync(userWalletId, currency) diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt index 8814392d0a..bfda6741cd 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt @@ -30,7 +30,6 @@ import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.tokens.model.* import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.tokens.repository.QuotesRepository import com.tangem.domain.tokens.utils.extractAddress import com.tangem.domain.wallets.models.UserWalletId @@ -43,7 +42,6 @@ class CachedCurrenciesStatusesOperations( private val currenciesRepository: CurrenciesRepository, private val quotesRepository: QuotesRepository, quotesRepositoryV2: QuotesRepositoryV2, - private val networksRepository: NetworksRepository, private val stakingRepository: StakingRepository, private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier, multiNetworkStatusSupplier: MultiNetworkStatusSupplier, @@ -58,7 +56,6 @@ class CachedCurrenciesStatusesOperations( currenciesRepository = currenciesRepository, quotesRepository = quotesRepository, quotesRepositoryV2 = quotesRepositoryV2, - networksRepository = networksRepository, stakingRepository = stakingRepository, multiNetworkStatusSupplier = multiNetworkStatusSupplier, singleNetworkStatusSupplier = singleNetworkStatusSupplier, @@ -156,7 +153,7 @@ class CachedCurrenciesStatusesOperations( combine( flow = getQuotes(currenciesIds), - flow2 = getNetworksStatuses(userWalletId, networks), + flow2 = getNetworkStatusesUpdates(userWalletId, networks), flow3 = getYieldBalances(userWalletId, currencies), flow4 = fetchingState.map { val state = it[userWalletId] ?: return@map false @@ -184,13 +181,9 @@ class CachedCurrenciesStatusesOperations( coroutineScope { awaitAll( async { - if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - multiNetworkStatusFetcher( - params = MultiNetworkStatusFetcher.Params(userWalletId, networks), - ) - } else { - networksRepository.fetchNetworkStatuses(userWalletId, networks) - } + multiNetworkStatusFetcher( + params = MultiNetworkStatusFetcher.Params(userWalletId = userWalletId, networks = networks), + ) }, async { val rawCurrenciesIds = currenciesIds.mapNotNullTo(mutableSetOf()) { it.rawCurrencyId } @@ -327,44 +320,12 @@ class CachedCurrenciesStatusesOperations( userWalletId: UserWalletId, network: Network, ): EitherFlow> { - return if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - singleNetworkStatusSupplier( - params = SingleNetworkStatusProducer.Params(userWalletId = userWalletId, network = network), - ) - .map>> { setOf(it).right() } - .distinctUntilChanged() - .onEmpty { emit(Error.EmptyNetworksStatuses.left()) } - } else { - networksRepository.getNetworkStatusesUpdates(userWalletId, setOf(network)) - .map, Either>> { it.right() } - .retryWhen { cause, _ -> - emit(Error.DataError(cause).left()) - // adding delay before retry to avoid spam when flow restarted - delay(RETRY_DELAY) - true - } - .distinctUntilChanged() - .onEmpty { emit(Error.EmptyNetworksStatuses.left()) } - } - } - - private fun getNetworksStatuses( - userWalletId: UserWalletId, - networks: NonEmptySet, - ): EitherFlow> { - return if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - getNetworkStatusesUpdates(userWalletId, networks) - } else { - networksRepository.getNetworkStatusesUpdates(userWalletId, networks) - .map, Either>> { it.right() } - .retryWhen { cause, _ -> - emit(TokenListError.DataError(cause).left()) - // adding delay before retry to avoid spam when flow restarted - delay(RETRY_DELAY) - true - } - .distinctUntilChanged() - } + return singleNetworkStatusSupplier( + params = SingleNetworkStatusProducer.Params(userWalletId = userWalletId, network = network), + ) + .map>> { setOf(it).right() } + .distinctUntilChanged() + .onEmpty { emit(Error.EmptyNetworksStatuses.left()) } } private fun getYieldBalances( diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCaseTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCaseTest.kt deleted file mode 100644 index be180baa2f..0000000000 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCaseTest.kt +++ /dev/null @@ -1,197 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import arrow.core.left -import arrow.core.right -import com.tangem.domain.core.error.DataError -import com.tangem.domain.tokens.error.CurrencyStatusError -import com.tangem.domain.tokens.mock.MockNetworks -import com.tangem.domain.tokens.mock.MockQuotes -import com.tangem.domain.tokens.mock.MockTokens -import com.tangem.domain.tokens.mock.MockTokensStates -import com.tangem.domain.tokens.model.* -import com.tangem.domain.tokens.operations.CachedCurrenciesStatusesOperations -import com.tangem.domain.tokens.repository.MockCurrenciesRepository -import com.tangem.domain.tokens.repository.MockNetworksRepository -import com.tangem.domain.tokens.repository.MockQuotesRepository -import com.tangem.domain.tokens.repository.MockStakingRepository -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider -import io.mockk.mockk -import junit.framework.TestCase.assertEquals -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.test.runTest -import org.junit.Test -import java.math.BigDecimal - -internal class GetPrimaryCurrencyStatusUpdatesUseCaseTest { - - private val dispatchers = TestingCoroutineDispatcherProvider() - private val userWalletId = UserWalletId(value = null) - - @Test - fun `when all data received then token should be received`() = runTest { - // Given - val expectedResult = MockTokensStates.loadedTokensStates.first().right() - - val useCase = getUseCase() - - // When - val result = useCase(userWalletId).first() - - // Then - assertEquals(expectedResult, result) - } - - @Test - fun `when token getting failed then error should be received`() = runTest { - // Given - val expectedResult = CurrencyStatusError.DataError(DataError.NetworkError.NoInternetConnection).left() - - val useCase = getUseCase(token = DataError.NetworkError.NoInternetConnection.left()) - - // When - val result = useCase(userWalletId).first() - - // Then - assertEquals(expectedResult, result) - } - - @Test - fun `when quotes getting failed then currency with no quote status should be received`() = runTest { - // Given - val expectedResult = MockTokensStates.noQuotesTokensStatuses.first().right() - - val useCase = getUseCase(quotes = flowOf(DataError.NetworkError.NoInternetConnection.left())) - - // When - val result = useCase(userWalletId).first() - - // Then - assertEquals(expectedResult, result) - } - - @Test - fun `when networks statuses getting failed then error should be received`() = runTest { - // Given - val expectedResult = CurrencyStatusError.DataError(DataError.NetworkError.NoInternetConnection).left() - - val useCase = getUseCase(statuses = flowOf(DataError.NetworkError.NoInternetConnection.left())) - - // When - val result = useCase(userWalletId).first() - - // Then - assertEquals(expectedResult, result) - } - - @Test - fun `when networks statuses flow is empty then error should be received`() = runTest { - val expectedResult = CurrencyStatusError.UnableToCreateCurrency.left() - - val useCase = getUseCase(statuses = flowOf()) - - // When - val result = useCase(userWalletId).first() - - // Then - assertEquals(expectedResult, result) - } - - @Test - fun `when quotes flow is empty then no quote status should be received`() = runTest { - val expectedResult = MockTokensStates.noQuotesTokensStatuses.first().right() - - val useCase = getUseCase(quotes = flowOf(emptySet().right())) - - // When - val result = useCase(userWalletId).first() - - // Then - assertEquals(expectedResult, result) - } - - @Test - fun `when quotes are empty and statuses are verified then token without quote should be received`() = runTest { - val expectedResult = with(MockTokensStates.tokenState1) { - copy( - value = CryptoCurrencyStatus.NoQuote( - amount = BigDecimal.TEN, - hasCurrentNetworkTransactions = false, - pendingTransactions = emptySet(), - networkAddress = NetworkAddress.Single( - defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), - ), - yieldBalance = null, - sources = CryptoCurrencyStatus.Sources(), - ), - ) - } - .right() - - val useCase = getUseCase( - statuses = flowOf(MockNetworks.verifiedNetworksStatuses.right()), - quotes = flowOf(emptySet().right()), - ) - - // When - val result = useCase(userWalletId).first() - - // Then - assertEquals(expectedResult, result) - } - - @Test - fun `when quotes are loaded and statuses are empty then error be received`() = runTest { - val expectedResult = CurrencyStatusError.UnableToCreateCurrency.left() - - val useCase = getUseCase( - statuses = flowOf(emptySet().right()), - quotes = flowOf(MockQuotes.quotes.right()), - ) - - // When - val result = useCase(userWalletId).first() - - // Then - assertEquals(expectedResult, result) - } - - private fun getUseCase( - token: Either = MockTokens.token1.right(), - removeCurrencyResult: Either = Unit.right(), - quotes: Flow>> = flowOf(MockQuotes.quotes.right()), - statuses: Flow>> = flowOf(MockNetworks.verifiedNetworksStatuses.right()), - ) = GetPrimaryCurrencyStatusUpdatesUseCase( - currencyStatusOperations = CachedCurrenciesStatusesOperations( - currenciesRepository = MockCurrenciesRepository( - sortTokensResult = Unit.right(), - removeCurrencyResult = removeCurrencyResult, - token = token, - tokens = flowOf(), - isGrouped = flowOf(), - isSortedByBalance = flowOf(), - ), - quotesRepository = MockQuotesRepository(quotes), - networksRepository = MockNetworksRepository(statuses), - stakingRepository = MockStakingRepository(), - - tokensFeatureToggles = object : TokensFeatureToggles { - override val isNetworksLoadingRefactoringEnabled: Boolean = false - override val isQuotesLoadingRefactoringEnabled: Boolean = false - override val isStakingLoadingRefactoringEnabled: Boolean = false - }, - singleNetworkStatusSupplier = mockk(), - multiNetworkStatusFetcher = mockk(), - multiNetworkStatusSupplier = mockk(), - multiQuoteFetcher = mockk(), - singleQuoteSupplier = mockk(), - quotesRepositoryV2 = mockk(), - singleYieldBalanceSupplier = mockk(), - multiYieldBalanceFetcher = mockk(), - ), - dispatchers = dispatchers, - ) -} \ No newline at end of file diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/AssociateAssetUseCase.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/AssociateAssetUseCase.kt index 3df20fa08d..f44929cdd3 100644 --- a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/AssociateAssetUseCase.kt +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/AssociateAssetUseCase.kt @@ -7,12 +7,10 @@ import com.tangem.blockchain.extensions.SimpleResult import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.networks.single.SingleNetworkStatusProducer import com.tangem.domain.networks.single.SingleNetworkStatusSupplier -import com.tangem.domain.tokens.TokensFeatureToggles import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyAmountStatus import com.tangem.domain.tokens.model.NetworkStatus import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.transaction.error.AssociateAssetError import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.models.UserWalletId @@ -23,9 +21,7 @@ class AssociateAssetUseCase( private val cardSdkConfigRepository: CardSdkConfigRepository, private val walletManagersFacade: WalletManagersFacade, private val currenciesRepository: CurrenciesRepository, - private val networksRepository: NetworksRepository, private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier, - private val tokensFeatureToggles: TokensFeatureToggles, ) { suspend operator fun invoke( @@ -59,20 +55,13 @@ class AssociateAssetUseCase( } private suspend fun isBalanceZero(userWalletId: UserWalletId, currency: CryptoCurrency): Boolean { - val networkStatus = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - singleNetworkStatusSupplier( - params = SingleNetworkStatusProducer.Params( - userWalletId = userWalletId, - network = currency.network, - ), - ) - .firstOrNull() - } else { - networksRepository.getNetworkStatusesSync( + val networkStatus = singleNetworkStatusSupplier( + params = SingleNetworkStatusProducer.Params( userWalletId = userWalletId, - networks = setOf(currency.network), - ).find { it.network == currency.network } - } + network = currency.network, + ), + ) + .firstOrNull() val networkCoinAmountStatus = (networkStatus?.value as? NetworkStatus.Verified) ?.amounts 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 15efbc7500..e519d17ac5 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 @@ -19,7 +19,6 @@ import com.tangem.domain.common.TapWorkarounds.isTangemTwins import com.tangem.domain.demo.DemoConfig import com.tangem.domain.demo.DemoTransactionSender import com.tangem.domain.networks.single.SingleNetworkStatusFetcher -import com.tangem.domain.tokens.TokensFeatureToggles import com.tangem.domain.tokens.model.Network import com.tangem.domain.transaction.TransactionRepository import com.tangem.domain.transaction.error.SendTransactionError @@ -33,7 +32,6 @@ class SendTransactionUseCase( private val transactionRepository: TransactionRepository, private val walletManagersFacade: WalletManagersFacade, private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher, - private val tokensFeatureToggles: TokensFeatureToggles, ) { suspend operator fun invoke( txsData: List, @@ -80,16 +78,15 @@ class SendTransactionUseCase( } cardSdkConfigRepository.setLinkedTerminal(linkedTerminal) + return sendResult .onRight { - if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - singleNetworkStatusFetcher( - params = SingleNetworkStatusFetcher.Params( - userWalletId = userWallet.walletId, - network = network, - ), - ) - } + singleNetworkStatusFetcher( + params = SingleNetworkStatusFetcher.Params( + userWalletId = userWallet.walletId, + network = network, + ), + ) } .fold( ifRight = { result -> result.hashes.right() }, diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcPairRequest.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcPairRequest.kt index 1c1c3f3674..2d70af0e55 100644 --- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcPairRequest.kt +++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcPairRequest.kt @@ -1,11 +1,13 @@ package com.tangem.domain.walletconnect.model +import com.tangem.domain.wallets.models.UserWalletId import kotlinx.serialization.Serializable @Serializable data class WcPairRequest( val uri: String, val source: Source, + val userWalletId: UserWalletId, ) { enum class Source { QR, DEEPLINK, CLIPBOARD, ETC } } \ No newline at end of file diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSession.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSession.kt index d3707d52f6..a2b1449d45 100644 --- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSession.kt +++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSession.kt @@ -1,11 +1,13 @@ package com.tangem.domain.walletconnect.model import com.domain.blockaid.models.dapp.CheckDAppResult +import com.tangem.domain.tokens.model.Network import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSession import com.tangem.domain.wallets.models.UserWallet data class WcSession( val wallet: UserWallet, + val networks: Set, val sdkModel: WcSdkSession, val securityStatus: CheckDAppResult, ) \ No newline at end of file diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetCardImageUseCase.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetCardImageUseCase.kt index 048729f9e9..7a71823750 100644 --- a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetCardImageUseCase.kt +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetCardImageUseCase.kt @@ -1,5 +1,6 @@ package com.tangem.domain.wallets.usecase +import com.tangem.common.card.FirmwareVersion import com.tangem.common.extensions.toHexString import com.tangem.common.services.Result import com.tangem.domain.common.TwinCardNumber @@ -30,11 +31,19 @@ class GetCardImageUseCase( * @param cardId card id * @param cardPublicKey card public key */ - suspend operator fun invoke(cardId: String, cardPublicKey: ByteArray, size: ArtworkSize): ArtworkModel { + suspend operator fun invoke( + cardId: String, + cardPublicKey: ByteArray, + manufacturerName: String, + firmwareVersion: FirmwareVersion, + size: ArtworkSize, + ): ArtworkModel { return if (cardSdkFeatureToggles.isNewArtworkLoadingEnabled) { val result = cardArtworksProvider.getArtwork( cardId = cardId, cardPublicKey = cardPublicKey, + manufacturerName = manufacturerName, + firmwareVersion = firmwareVersion, size = size, ) when (result) { diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/component/preview/PreviewDetailsComponent.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/component/preview/PreviewDetailsComponent.kt index 37abe05472..8efcb31776 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/component/preview/PreviewDetailsComponent.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/component/preview/PreviewDetailsComponent.kt @@ -5,6 +5,7 @@ import androidx.compose.ui.Modifier import com.tangem.core.decompose.navigation.DummyRouter import com.tangem.core.navigation.url.DummyUrlOpener import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.features.details.component.DetailsComponent import com.tangem.features.details.entity.DetailsFooterUM import com.tangem.features.details.entity.DetailsUM @@ -18,7 +19,12 @@ internal class PreviewDetailsComponent : DetailsComponent { private val previewBlocks = runBlocking { ItemsBuilder( router = DummyRouter(), - ).buildAll(isWalletConnectAvailable = true, onSupportClick = {}, onBuyClick = {}) + ).buildAll( + isWalletConnectAvailable = true, + userWalletId = UserWalletId(""), + onSupportClick = {}, + onBuyClick = {}, + ) } private val previewFooter = DetailsFooterUM( diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt index d2068c9fcf..10afab1fde 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt @@ -80,6 +80,7 @@ internal class DetailsModel @Inject constructor( items = MutableStateFlow( itemsBuilder.buildAll( isWalletConnectAvailable = isWalletConnectAvailable, + userWalletId = params.userWalletId, onSupportClick = ::sendFeedback, onBuyClick = ::onBuyClick, ), diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt index 7cd8933ad5..f0fd520172 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt @@ -6,6 +6,7 @@ import com.tangem.core.decompose.navigation.Router import com.tangem.core.ui.components.block.model.BlockUM import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.features.details.entity.DetailsItemUM import com.tangem.features.details.impl.BuildConfig import com.tangem.features.details.impl.R @@ -19,20 +20,21 @@ internal class ItemsBuilder @Inject constructor(private val router: Router) { fun buildAll( isWalletConnectAvailable: Boolean, + userWalletId: UserWalletId, onSupportClick: () -> Unit, onBuyClick: () -> Unit, ): ImmutableList = buildList { - buildWalletConnectBlock(isWalletConnectAvailable)?.let(::add) + buildWalletConnectBlock(isWalletConnectAvailable, userWalletId)?.let(::add) buildUserWalletListBlock().let(::add) buildShopBlock(onBuyClick).let(::add) buildSettingsBlock().let(::add) buildSupportBlock(onSupportClick).let(::add) }.toImmutableList() - private fun buildWalletConnectBlock(isWalletConnectAvailable: Boolean): DetailsItemUM? { + private fun buildWalletConnectBlock(isWalletConnectAvailable: Boolean, userWalletId: UserWalletId): DetailsItemUM? { return if (isWalletConnectAvailable) { DetailsItemUM.WalletConnect( - onClick = { router.push(AppRoute.WalletConnectSessions) }, + onClick = { router.push(AppRoute.WalletConnectSessions(userWalletId)) }, ) } else { null diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletsFetcher.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletsFetcher.kt index 23cde30f76..344068b99b 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletsFetcher.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletsFetcher.kt @@ -87,6 +87,8 @@ internal class UserWalletsFetcher @Inject constructor( wallets.forEach { wallet -> val artwork = getCardImageUseCase( cardId = wallet.cardId, + manufacturerName = wallet.scanResponse.card.manufacturer.name, + firmwareVersion = wallet.scanResponse.card.firmwareVersion.toSdkFirmwareVersion(), cardPublicKey = wallet.scanResponse.card.cardPublicKey, size = ArtworkSize.SMALL, ) diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/model/NFTCollectionsModel.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/model/NFTCollectionsModel.kt index 72b200907a..1b83ed39e4 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/model/NFTCollectionsModel.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/model/NFTCollectionsModel.kt @@ -15,10 +15,6 @@ import com.tangem.features.nft.collections.NFTCollectionsComponent import com.tangem.features.nft.collections.entity.NFTCollectionsStateUM import com.tangem.features.nft.collections.entity.NFTCollectionsUM import com.tangem.features.nft.collections.entity.transformer.* -import com.tangem.features.nft.collections.entity.transformer.ChangeCollectionExpandedStateTransformer -import com.tangem.features.nft.collections.entity.transformer.ToggleSearchBarTransformer -import com.tangem.features.nft.collections.entity.transformer.UpdateDataStateTransformer -import com.tangem.features.nft.collections.entity.transformer.UpdateSearchQueryTransformer import com.tangem.features.nft.impl.R import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.* diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/MultiWalletChildParams.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/MultiWalletChildParams.kt index 8fee788c8b..12c16a3ee2 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/MultiWalletChildParams.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/MultiWalletChildParams.kt @@ -1,5 +1,7 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child +import com.tangem.common.card.Card.Manufacturer +import com.tangem.common.card.FirmwareVersion import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent import com.tangem.features.onboarding.v2.multiwallet.impl.MultiWalletInnerNavigationState import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState @@ -18,6 +20,8 @@ class MultiWalletChildParams( data class BackupCardInfo( val cardId: String, val cardPublicKey: ByteArray, + val manufacturer: Manufacturer, + val firmwareVersion: FirmwareVersion, ) { override fun equals(other: Any?): Boolean { if (this === other) return true diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt index e9be6ab78d..cee887eceb 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt @@ -206,6 +206,8 @@ class MultiWalletBackupModel @Inject constructor( val backupCardInfo = MultiWalletChildParams.Backup.BackupCardInfo( cardId = result.data.cardId, cardPublicKey = result.data.cardPublicKey, + manufacturer = result.data.manufacturer, + firmwareVersion = result.data.firmwareVersion, ) params.backups.update { it.copy( diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt index c685d24d3c..6d5a640d3d 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt @@ -86,6 +86,8 @@ internal class OnboardingMultiWalletModel @Inject constructor( cardId = backup.card2.cardId, cardPublicKey = backup.card2.cardPublicKey, size = ArtworkSize.LARGE, + manufacturerName = backup.card2.manufacturer.name, + firmwareVersion = backup.card2.firmwareVersion, ) _uiState.update { it.copy(artwork2 = ArtworkUM(artwork.verifiedArtwork, artwork.defaultUrl)) @@ -97,6 +99,8 @@ internal class OnboardingMultiWalletModel @Inject constructor( cardId = backup.card3.cardId, cardPublicKey = backup.card3.cardPublicKey, size = ArtworkSize.LARGE, + manufacturerName = backup.card3.manufacturer.name, + firmwareVersion = backup.card3.firmwareVersion, ) _uiState.update { it.copy(artwork3 = ArtworkUM(artwork.verifiedArtwork, artwork.defaultUrl)) @@ -170,6 +174,8 @@ internal class OnboardingMultiWalletModel @Inject constructor( cardId = params.scanResponse.card.cardId, cardPublicKey = params.scanResponse.card.cardPublicKey, size = ArtworkSize.LARGE, + manufacturerName = params.scanResponse.card.manufacturer.name, + firmwareVersion = params.scanResponse.card.firmwareVersion.toSdkFirmwareVersion(), ) _uiState.update { diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/child/topup/model/OnboardingNoteTopUpModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/child/topup/model/OnboardingNoteTopUpModel.kt index bdac9d90ca..7330ae8a68 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/child/topup/model/OnboardingNoteTopUpModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/child/topup/model/OnboardingNoteTopUpModel.kt @@ -16,7 +16,7 @@ import com.tangem.domain.exchange.RampStateManager import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.onramp.GetLegacyTopUpUrlUseCase import com.tangem.domain.tokens.FetchCurrencyStatusUseCase -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.Network import com.tangem.domain.tokens.model.NetworkAddress @@ -39,7 +39,7 @@ import javax.inject.Inject internal class OnboardingNoteTopUpModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, private val userWalletBuilderFactory: UserWalletBuilder.Factory, private val getLegacyTopUpUrlUseCase: GetLegacyTopUpUrlUseCase, @@ -137,8 +137,11 @@ internal class OnboardingNoteTopUpModel @Inject constructor( private fun observeCryptoCurrencyStatus() { val userWalletId = userWallet?.walletId ?: return - getPrimaryCurrencyStatusUpdatesUseCase(userWalletId = userWalletId).map { it.getOrNull() }.filterNotNull() - .onEach(::applyCryptoCurrencyStatusToState).launchIn(modelScope) + getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWalletId = userWalletId) + .map { it.getOrNull() } + .filterNotNull() + .onEach(::applyCryptoCurrencyStatusToState) + .launchIn(modelScope) } private fun applyCryptoCurrencyStatusToState(status: CryptoCurrencyStatus) { diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/model/OnboardingNoteModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/model/OnboardingNoteModel.kt index 43303a39b2..43d12d119e 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/model/OnboardingNoteModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/model/OnboardingNoteModel.kt @@ -94,6 +94,8 @@ internal class OnboardingNoteModel @Inject constructor( cardId = cardInfo.cardId, cardPublicKey = cardInfo.cardPublicKey, size = ArtworkSize.LARGE, + manufacturerName = cardInfo.manufacturer.name, + firmwareVersion = cardInfo.firmwareVersion.toSdkFirmwareVersion(), ) _uiState.update { it.copy(cardArtwork = ArtworkUM(artwork.verifiedArtwork, artwork.defaultUrl)) diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/twin/impl/model/OnboardingTwinModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/twin/impl/model/OnboardingTwinModel.kt index 1219a5763f..a36e14fec8 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/twin/impl/model/OnboardingTwinModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/twin/impl/model/OnboardingTwinModel.kt @@ -7,18 +7,18 @@ import com.tangem.common.core.TangemError import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.hexToBytes import com.tangem.common.extensions.toHexString +import com.tangem.common.ui.bottomsheet.receive.TokenReceiveBottomSheetConfig +import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender -import com.tangem.core.navigation.url.UrlOpener -import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig -import com.tangem.common.ui.bottomsheet.receive.TokenReceiveBottomSheetConfig -import com.tangem.core.analytics.Analytics import com.tangem.core.navigation.share.ShareManager +import com.tangem.core.navigation.url.UrlOpener import com.tangem.core.ui.clipboard.ClipboardManager +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.toWrappedList import com.tangem.core.ui.format.bigdecimal.crypto @@ -34,7 +34,7 @@ import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase import com.tangem.domain.onramp.GetLegacyTopUpUrlUseCase import com.tangem.domain.tokens.FetchCurrencyStatusUseCase -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.Network import com.tangem.domain.tokens.model.analytics.TokenReceiveAnalyticsEvent @@ -77,7 +77,7 @@ internal class OnboardingTwinModel @Inject constructor( private val tangemSdkManager: TangemSdkManager, private val issuersConfigStorage: IssuersConfigStorage, private val cardRepository: CardRepository, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, private val getLegacyTopUpUrlUseCase: GetLegacyTopUpUrlUseCase, private val urlOpener: UrlOpener, @@ -337,16 +337,16 @@ internal class OnboardingTwinModel @Inject constructor( setLoading(false) } - val cryptoCurrencyStatus = - getPrimaryCurrencyStatusUpdatesUseCase.invoke(userWallet.walletId).firstOrNull()?.getOrNull() - ?: run { - setLoading(false) - Timber.e("Unable to get currency status") - return@coroutineScope - } + val cryptoCurrencyStatus = getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWallet.walletId) + .firstOrNull()?.getOrNull() + ?: run { + setLoading(false) + Timber.e("Unable to get currency status") + return@coroutineScope + } launch { - getPrimaryCurrencyStatusUpdatesUseCase.invoke(userWallet.walletId) + getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWallet.walletId) .collect { it.onRight { status -> applyCryptoCurrencyStatusToState(status) diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/model/HotCryptoModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/model/HotCryptoModel.kt index be622c09d1..cb7ccfc863 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/model/HotCryptoModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/model/HotCryptoModel.kt @@ -14,7 +14,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.onramp.GetHotCryptoUseCase import com.tangem.domain.onramp.model.HotCryptoCurrency -import com.tangem.domain.tokens.GetCryptoCurrencyStatusSyncUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.features.onramp.hottokens.HotCryptoComponent import com.tangem.features.onramp.hottokens.converter.HotTokenItemStateConverter @@ -45,7 +45,7 @@ internal class HotCryptoModel @Inject constructor( paramsContainer: ParamsContainer, getHotCryptoUseCase: GetHotCryptoUseCase, getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, - private val getCryptoCurrencyStatusSyncUseCase: GetCryptoCurrencyStatusSyncUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, override val dispatchers: CoroutineDispatcherProvider, ) : Model() { @@ -103,7 +103,10 @@ internal class HotCryptoModel @Inject constructor( private fun onSuccessAdding(id: CryptoCurrency.ID) { modelScope.launch { - getCryptoCurrencyStatusSyncUseCase(userWalletId = params.userWalletId, cryptoCurrencyId = id) + getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync( + userWalletId = params.userWalletId, + cryptoCurrencyId = id, + ) .onRight { bottomSheetNavigation.dismiss() params.onTokenClick(it) 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 69254405cf..bb10f2b5d3 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 @@ -52,7 +52,6 @@ internal class SendBalanceUpdater @AssistedInject constructor( userWalletId = userWallet.walletId, network = cryptoCurrency.network, delayMillis = delay, - refresh = true, ) } diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt index 250e790576..3d162a7bc2 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt @@ -23,9 +23,8 @@ import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.qrscanning.models.SourceType import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase -import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.transaction.error.GetFeeError @@ -72,8 +71,7 @@ internal class SendModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val router: Router, private val getUserWalletUseCase: GetUserWalletUseCase, - private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val listenToQrScanningUseCase: ListenToQrScanningUseCase, @@ -244,13 +242,13 @@ internal class SendModel @Inject constructor( isMultiCurrency: Boolean, ): Flow> { return if (isMultiCurrency) { - getCurrencyStatusUpdatesUseCase( + getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( userWalletId = userWalletId, currencyId = cryptoCurrency.id, isSingleWalletWithTokens = isSingleWalletWithToken, ) } else { - getPrimaryCurrencyStatusUpdatesUseCase(userWalletId = userWalletId) + getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWalletId = userWalletId) } } diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt index 4e496e2810..ecd6c008dd 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt @@ -19,7 +19,7 @@ import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.BlockchainErrorInfo import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase -import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus @@ -60,7 +60,7 @@ internal class NFTSendModel @Inject constructor( private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, private val getCryptoCurrenciesUseCase: GetCryptoCurrenciesUseCase, - private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val createNFTTransferTransactionUseCase: CreateNFTTransferTransactionUseCase, private val getFeeUseCase: GetFeeUseCase, @@ -183,7 +183,7 @@ internal class NFTSendModel @Inject constructor( } private fun getCurrenciesStatusUpdates(isSingleWalletWithToken: Boolean) { - getCurrencyStatusUpdatesUseCase( + getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( userWalletId = userWalletId, currencyId = cryptoCurrency.id, isSingleWalletWithTokens = isSingleWalletWithToken, diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt index be16dae8cd..02f0478ef5 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt @@ -84,7 +84,7 @@ import kotlin.properties.Delegates internal class SendModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val getUserWalletUseCase: GetUserWalletUseCase, - private val getCryptoCurrencyStatusSyncUseCase: GetCryptoCurrencyStatusSyncUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getWalletsUseCase: GetWalletsUseCase, private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, @@ -325,13 +325,13 @@ internal class SendModel @Inject constructor( isMultiCurrency: Boolean, ): Either { return if (isMultiCurrency) { - getCryptoCurrencyStatusSyncUseCase( + getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync( userWalletId = userWalletId, cryptoCurrencyId = cryptoCurrency.id, isSingleWalletWithTokens = isSingleWalletWithToken, ) } else { - getCryptoCurrencyStatusSyncUseCase(userWalletId = userWalletId) + getSingleCryptoCurrencyStatusUseCase.invokeSingleWalletSync(userWalletId = userWalletId) } } @@ -1048,7 +1048,6 @@ internal class SendModel @Inject constructor( userWalletId = userWallet.walletId, network = cryptoCurrency.network, delayMillis = BALANCE_UPDATE_DELAY, - refresh = true, ) }, ).awaitAll() 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 d122cd48bf..c8eb096676 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 @@ -93,7 +93,7 @@ internal class StakingModel @Inject constructor( private val stateController: StakingStateController, override val dispatchers: CoroutineDispatcherProvider, private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, - private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val getMinimumTransactionAmountSyncUseCase: GetMinimumTransactionAmountSyncUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, @@ -920,7 +920,7 @@ internal class StakingModel @Inject constructor( ) }, ) - getCurrencyStatusUpdatesUseCase( + getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( userWalletId = userWalletId, currencyId = cryptoCurrencyId, isSingleWalletWithTokens = false, 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 02db8ad802..88d2974d5c 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 @@ -83,7 +83,6 @@ internal class StakingBalanceUpdater @AssistedInject constructor( userWalletId = userWallet.walletId, network = cryptoCurrencyStatus.currency.network, delayMillis = delay, - refresh = true, ) } diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index 6d119df85d..1e45b523de 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -18,7 +18,7 @@ import com.tangem.domain.appcurrency.repository.AppCurrencyRepository import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.quotes.QuotesRepositoryV2 import com.tangem.domain.tokens.FetchCurrencyStatusUseCase -import com.tangem.domain.tokens.GetCryptoCurrencyStatusesSyncUseCase +import com.tangem.domain.tokens.GetMultiCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.GetCurrencyCheckUseCase import com.tangem.domain.tokens.TokensFeatureToggles import com.tangem.domain.tokens.model.* @@ -54,7 +54,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( private val userWalletManager: UserWalletManager, private val repository: SwapRepository, private val allowPermissionsHandler: AllowPermissionsHandler, - private val getMultiCryptoCurrencyStatusUseCase: GetCryptoCurrencyStatusesSyncUseCase, + private val getMultiCryptoCurrencyStatusUseCase: GetMultiCryptoCurrencyStatusUseCase, private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, private val sendTransactionUseCase: SendTransactionUseCase, private val createTransactionUseCase: CreateTransactionUseCase, @@ -92,7 +92,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( } override suspend fun getTokensDataState(currency: CryptoCurrency): TokensDataStateExpress { - val walletCurrencyStatuses = getMultiCryptoCurrencyStatusUseCase(userWalletId) + val walletCurrencyStatuses = getMultiCryptoCurrencyStatusUseCase.invokeMultiWalletSync(userWalletId) .getOrElse { emptyList() } val walletCurrencyStatusesExceptInitial = walletCurrencyStatuses diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt index 610aa556a8..7a7e89069d 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt @@ -1,6 +1,6 @@ package com.tangem.feature.swap.domain.di -import com.tangem.domain.tokens.GetCryptoCurrencyStatusesSyncUseCase +import com.tangem.domain.tokens.GetMultiCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations import com.tangem.feature.swap.domain.* import dagger.Module @@ -28,8 +28,8 @@ internal class SwapDomainModule { @Singleton fun providesGetCryptoCurrencyStatusUseCase( currencyStatusOperations: BaseCurrencyStatusOperations, - ): GetCryptoCurrencyStatusesSyncUseCase { - return GetCryptoCurrencyStatusesSyncUseCase(currencyStatusOperations) + ): GetMultiCryptoCurrencyStatusUseCase { + return GetMultiCryptoCurrencyStatusUseCase(currencyStatusOperations) } @Provides diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt index 0b3a1eb4b5..2c54085052 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt @@ -34,7 +34,10 @@ import com.tangem.domain.promo.models.StoryContentIds import com.tangem.domain.settings.usercountry.GetUserCountryUseCase import com.tangem.domain.settings.usercountry.models.UserCountry import com.tangem.domain.settings.usercountry.models.needApplyFCARestrictions -import com.tangem.domain.tokens.* +import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase +import com.tangem.domain.tokens.GetMinimumTransactionAmountSyncUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase +import com.tangem.domain.tokens.UpdateDelayedNetworkStatusUseCase import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.Network @@ -86,9 +89,8 @@ internal class SwapModel @Inject constructor( private val analyticsEventHandler: AnalyticsEventHandler, private val analyticsErrorEventHandler: AnalyticsErrorHandler, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, - private val getCryptoCurrencyStatusUseCase: GetCryptoCurrencyStatusSyncUseCase, private val updateDelayedCurrencyStatusUseCase: UpdateDelayedNetworkStatusUseCase, - private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, private val getCardInfoUseCase: GetCardInfoUseCase, @@ -98,7 +100,7 @@ internal class SwapModel @Inject constructor( private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, private val shouldShowStoriesUseCase: ShouldShowStoriesUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, - private val getUserCountryUseCase: GetUserCountryUseCase, + getUserCountryUseCase: GetUserCountryUseCase, getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, swapInteractorFactory: SwapInteractor.Factory, private val urlOpener: UrlOpener, @@ -176,8 +178,12 @@ internal class SwapModel @Inject constructor( } modelScope.launch(dispatchers.io) { - val fromStatus = getCryptoCurrencyStatusUseCase(userWalletId, initialCurrencyFrom.id).getOrNull() - val toStatus = initialCurrencyTo?.let { getCryptoCurrencyStatusUseCase(userWalletId, it.id).getOrNull() } + val fromStatus = + getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync(userWalletId, initialCurrencyFrom.id) + .getOrNull() + val toStatus = initialCurrencyTo?.let { + getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync(userWalletId, it.id).getOrNull() + } val wallet = getUserWalletUseCase(userWalletId).getOrNull() if (fromStatus == null || wallet == null) { @@ -861,7 +867,7 @@ internal class SwapModel @Inject constructor( ) { Timber.d("Subscribe to ${coin.id} balance updates") - getCurrencyStatusUpdatesUseCase( + getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( userWalletId = userWalletId, currencyId = coin.id, isSingleWalletWithTokens = false, @@ -1311,7 +1317,6 @@ internal class SwapModel @Inject constructor( userWalletId = userWalletId, network = network, delayMillis = UPDATE_BALANCE_DELAY_MILLIS, - refresh = true, ) } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt index 4d4b8bc5e7..669086fb61 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt @@ -91,7 +91,7 @@ import javax.inject.Inject @ModelScoped internal class TokenDetailsModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, - private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase, @@ -117,7 +117,6 @@ internal class TokenDetailsModel @Inject constructor( private val analyticsEventsHandler: AnalyticsEventHandler, private val vibratorHapticManager: VibratorHapticManager, private val clipboardManager: ClipboardManager, - private val getCryptoCurrencySyncUseCase: GetCryptoCurrencyStatusSyncUseCase, private val onrampFeatureToggles: OnrampFeatureToggles, private val shareManager: ShareManager, @GlobalUiMessageSender private val uiMessageSender: UiMessageSender, @@ -219,7 +218,7 @@ internal class TokenDetailsModel @Inject constructor( private fun initButtons() { // we need also init buttons before start all loading to avoid buttons blocking modelScope.launch { - val currentCryptoCurrencyStatus = getCryptoCurrencySyncUseCase.invoke( + val currentCryptoCurrencyStatus = getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync( userWalletId = userWalletId, cryptoCurrencyId = cryptoCurrency.id, isSingleWalletWithTokens = false, @@ -300,7 +299,7 @@ internal class TokenDetailsModel @Inject constructor( private fun subscribeOnCurrencyStatusUpdates() { modelScope.launch(dispatchers.main) { - getCurrencyStatusUpdatesUseCase( + getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( userWalletId = userWalletId, currencyId = cryptoCurrency.id, isSingleWalletWithTokens = userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(), @@ -364,7 +363,6 @@ internal class TokenDetailsModel @Inject constructor( updateDelayedCurrencyStatusUseCase( userWalletId = userWalletId, network = toCryptoCurrency.network, - refresh = true, ) } } diff --git a/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/model/TxHistoryModel.kt b/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/model/TxHistoryModel.kt index fc7568fafc..13948922c0 100644 --- a/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/model/TxHistoryModel.kt +++ b/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/model/TxHistoryModel.kt @@ -8,7 +8,7 @@ import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.common.util.cardTypesResolver -import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.txhistory.models.TxHistoryStateError @@ -39,7 +39,7 @@ internal class TxHistoryModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase, - private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, private val urlOpener: UrlOpener, @@ -165,7 +165,7 @@ internal class TxHistoryModel @Inject constructor( val userWallet: UserWallet = requireNotNull(getUserWalletUseCase(params.userWalletId).getOrNull()) { "User wallet not found" } - getCurrencyStatusUpdatesUseCase( + getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( userWalletId = params.userWalletId, currencyId = params.currency.id, isSingleWalletWithTokens = userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt index f9790aaa18..4695f54f1a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt @@ -8,7 +8,7 @@ import com.tangem.domain.nft.analytics.NFTAnalyticsEvent import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.settings.ShouldShowMarketsTooltipUseCase import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.TokensAction import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.TokenActionsState @@ -67,7 +67,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( private val walletWarningsClickIntents: WalletWarningsClickIntentsImplementor, private val onrampStatusFactory: OnrampStatusFactory, private val getUserWalletUseCase: GetUserWalletUseCase, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, private val shouldShowMarketsTooltipUseCase: ShouldShowMarketsTooltipUseCase, @@ -162,7 +162,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( override fun onTransactionClick(txHash: String) { modelScope.launch(dispatchers.main) { - val currency = getPrimaryCurrencyStatusUpdatesUseCase.unwrap( + val currency = getSingleCryptoCurrencyStatusUseCase.unwrap( userWalletId = stateHolder.getSelectedWalletId(), ) ?.currency diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt index be96aa27a4..c4d18c7023 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt @@ -34,7 +34,7 @@ import com.tangem.domain.promo.GetStoryContentUseCase import com.tangem.domain.promo.models.StoryContentIds import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.staking.model.stakekit.Yield -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.IsCryptoCurrencyCoinCouldHideUseCase import com.tangem.domain.tokens.RemoveCurrencyUseCase import com.tangem.domain.tokens.legacy.TradeCryptoAction @@ -110,7 +110,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val walletManagersFacade: WalletManagersFacade, private val isDemoCardUseCase: IsDemoCardUseCase, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val isCryptoCurrencyCoinCouldHide: IsCryptoCurrencyCoinCouldHideUseCase, private val removeCurrencyUseCase: RemoveCurrencyUseCase, private val getExploreUrlUseCase: GetExploreUrlUseCase, @@ -489,7 +489,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( val userWalletId = stateHolder.getSelectedWalletId() modelScope.launch(dispatchers.main) { - val currencyStatus = getPrimaryCurrencyStatusUpdatesUseCase.unwrap(userWalletId) ?: return@launch + val currencyStatus = getSingleCryptoCurrencyStatusUseCase.unwrap(userWalletId) ?: return@launch when (val addresses = currencyStatus.value.networkAddress) { is NetworkAddress.Selectable -> { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt index fbe13e7f90..bdf8d3095b 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletWarningsClickIntents.kt @@ -19,9 +19,6 @@ import com.tangem.domain.promo.ShouldShowPromoWalletUseCase import com.tangem.domain.promo.models.PromoId import com.tangem.domain.settings.NeverToSuggestRateAppUseCase import com.tangem.domain.settings.RemindToRateAppLaterUseCase -import com.tangem.domain.tokens.FetchTokenListUseCase -import com.tangem.domain.tokens.FetchTokenListUseCase.RefreshMode -import com.tangem.domain.tokens.TokensFeatureToggles import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType @@ -91,7 +88,6 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( private val stateHolder: WalletStateController, private val walletEventSender: WalletEventSender, private val derivePublicKeysUseCase: DerivePublicKeysUseCase, - private val fetchTokenListUseCase: FetchTokenListUseCase, private val setCardWasScannedUseCase: SetCardWasScannedUseCase, private val neverToSuggestRateAppUseCase: NeverToSuggestRateAppUseCase, private val remindToRateAppLaterUseCase: RemindToRateAppLaterUseCase, @@ -105,7 +101,6 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase, private val urlOpener: UrlOpener, - private val tokensFeatureToggles: TokensFeatureToggles, private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher, private val appRouter: AppRouter, ) : BaseWalletClickIntents(), WalletWarningsClickIntents { @@ -148,22 +143,13 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( ).fold( ifLeft = { Timber.e(it, "Failed to derive public keys") }, ifRight = { - if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) { - multiNetworkStatusFetcher( - params = MultiNetworkStatusFetcher.Params( - userWalletId = userWallet.walletId, - networks = missedAddressCurrencies.map(CryptoCurrency::network).toSet(), - ), - ) - } else { - fetchTokenListUseCase( + multiNetworkStatusFetcher( + params = MultiNetworkStatusFetcher.Params( userWalletId = userWallet.walletId, - mode = RefreshMode.SKIP_CURRENCIES, - currencies = missedAddressCurrencies, - ).onLeft { - Timber.e("Unable to refresh token list: $it") - } - } + networks = missedAddressCurrencies.map(CryptoCurrency::network).toSet(), + ), + ) + .onLeft { Timber.e("Unable to refresh token list: $it") } }, ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt index b59d4bd433..e8b3b2aacb 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt @@ -7,7 +7,7 @@ import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.models.StatusSource import com.tangem.domain.settings.IsReadyToShowRateAppUseCase -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.wallets.models.UserWallet @@ -22,7 +22,7 @@ import javax.inject.Inject @ModelScoped internal class GetSingleWalletWarningsFactory @Inject constructor( - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val isDemoCardUseCase: IsDemoCardUseCase, private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase, private val isNeedToBackupUseCase: IsNeedToBackupUseCase, @@ -36,7 +36,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor( val cardTypesResolver = userWallet.scanResponse.cardTypesResolver return combine( - flow = getPrimaryCurrencyStatusUpdatesUseCase(userWallet.walletId), + flow = getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWallet.walletId), flow2 = isReadyToShowRateAppUseCase().conflate(), flow3 = isNeedToBackupUseCase(userWallet.walletId).conflate(), flow4 = getWalletsUseCase().conflate(), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/UseCaseExt.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/UseCaseExt.kt index 1ab1765968..d21c569563 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/UseCaseExt.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/UseCaseExt.kt @@ -1,7 +1,7 @@ package com.tangem.feature.wallet.presentation.wallet.domain import arrow.core.Either -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.wallets.models.UserWallet @@ -20,8 +20,8 @@ internal fun GetSelectedWalletSyncUseCase.unwrap(): UserWallet? { ) } -internal suspend fun GetPrimaryCurrencyStatusUpdatesUseCase.unwrap(userWalletId: UserWalletId): CryptoCurrencyStatus? { - return this(userWalletId) +internal suspend fun GetSingleCryptoCurrencyStatusUseCase.unwrap(userWalletId: UserWalletId): CryptoCurrencyStatus? { + return invokeSingleWallet(userWalletId) .conflate() .distinctUntilChanged() .filter(Either::isRight) @@ -35,11 +35,11 @@ internal suspend fun GetPrimaryCurrencyStatusUpdatesUseCase.unwrap(userWalletId: ) } -internal suspend fun GetPrimaryCurrencyStatusUpdatesUseCase.collectLatest( +internal suspend fun GetSingleCryptoCurrencyStatusUseCase.collectLatest( userWalletId: UserWalletId, onRight: suspend (CryptoCurrencyStatus) -> Unit, ) { - this(userWalletId = userWalletId) + invokeSingleWallet(userWalletId = userWalletId) .conflate() .distinctUntilChanged() .collectLatest { maybeStatus -> diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt index e4167b9c20..81601a2e31 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt @@ -6,7 +6,7 @@ import com.tangem.domain.onramp.GetOnrampTransactionsUseCase import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase import com.tangem.domain.wallets.models.UserWallet @@ -29,7 +29,7 @@ internal class SingleWalletContentLoader( private val clickIntents: WalletClickIntents, private val isRefresh: Boolean, private val stateHolder: WalletStateController, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase, private val getSingleWalletWarningsFactory: GetSingleWalletWarningsFactory, private val setWalletWithFundsFoundUseCase: SetWalletWithFundsFoundUseCase, @@ -48,7 +48,7 @@ internal class SingleWalletContentLoader( PrimaryCurrencySubscriber( userWallet = userWallet, stateHolder = stateHolder, - getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase, + getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase, setWalletWithFundsFoundUseCase = setWalletWithFundsFoundUseCase, getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, analyticsEventHandler = analyticsEventHandler, @@ -57,7 +57,7 @@ internal class SingleWalletContentLoader( userWallet = userWallet, stateHolder = stateHolder, clickIntents = clickIntents, - getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase, + getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase, getCryptoCurrencyActionsUseCase = getCryptoCurrencyActionsUseCase, ), SingleWalletNotificationsSubscriber( @@ -78,7 +78,7 @@ internal class SingleWalletContentLoader( clickIntents = clickIntents, getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, analyticsEventHandler = analyticsEventHandler, - getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase, + getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase, getOnrampTransactionsUseCase = getOnrampTransactionsUseCase, onrampRemoveTransactionUseCase = onrampRemoveTransactionUseCase, ), @@ -87,7 +87,7 @@ internal class SingleWalletContentLoader( isRefresh = isRefresh, stateHolder = stateHolder, clickIntents = clickIntents, - getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase, + getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase, txHistoryItemsCountUseCase = txHistoryItemsCountUseCase, txHistoryItemsUseCase = txHistoryItemsUseCase, ), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt index 6e8e164e92..22f8884acd 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt @@ -7,7 +7,7 @@ import com.tangem.domain.onramp.GetOnrampTransactionsUseCase import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase import com.tangem.domain.wallets.models.UserWallet @@ -22,7 +22,7 @@ import javax.inject.Inject @Suppress("LongParameterList") internal class SingleWalletContentLoaderFactory @Inject constructor( private val stateHolder: WalletStateController, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase, private val getSingleWalletWarningsFactory: GetSingleWalletWarningsFactory, private val setWalletWithFundsFoundUseCase: SetWalletWithFundsFoundUseCase, @@ -42,7 +42,7 @@ internal class SingleWalletContentLoaderFactory @Inject constructor( clickIntents = clickIntents, isRefresh = isRefresh, stateHolder = stateHolder, - getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase, + getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase, getCryptoCurrencyActionsUseCase = getCryptoCurrencyActionsUseCase, getSingleWalletWarningsFactory = getSingleWalletWarningsFactory, setWalletWithFundsFoundUseCase = setWalletWithFundsFoundUseCase, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/PrimaryCurrencySubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/PrimaryCurrencySubscriber.kt index 855300bc2c..c5fd60f86a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/PrimaryCurrencySubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/PrimaryCurrencySubscriber.kt @@ -8,7 +8,7 @@ import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.wallets.models.UserWallet @@ -23,7 +23,7 @@ import java.math.BigDecimal internal class PrimaryCurrencySubscriber( private val userWallet: UserWallet, private val stateHolder: WalletStateController, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val setWalletWithFundsFoundUseCase: SetWalletWithFundsFoundUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val analyticsEventHandler: AnalyticsEventHandler, @@ -33,7 +33,7 @@ internal class PrimaryCurrencySubscriber( coroutineScope: CoroutineScope, ): Flow, AppCurrency>> { return combine( - flow = getPrimaryCurrencyStatusUpdatesUseCase(userWallet.walletId) + flow = getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWallet.walletId) .conflate() .distinctUntilChanged(), flow2 = getSelectedAppCurrencyUseCase() diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletButtonsSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletButtonsSubscriber.kt index 3404216570..2066f30975 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletButtonsSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletButtonsSubscriber.kt @@ -1,7 +1,7 @@ package com.tangem.feature.wallet.presentation.wallet.subscribers import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.model.TokenActionsState import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents @@ -15,13 +15,13 @@ internal class SingleWalletButtonsSubscriber( private val userWallet: UserWallet, private val stateHolder: WalletStateController, private val clickIntents: WalletClickIntents, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase, ) : WalletSubscriber() { override fun create(coroutineScope: CoroutineScope): Flow { return channelFlow { - getPrimaryCurrencyStatusUpdatesUseCase.collectLatest(userWalletId = userWallet.walletId) { status -> + getSingleCryptoCurrencyStatusUseCase.collectLatest(userWalletId = userWallet.walletId) { status -> getCryptoCurrencyActionsUseCase(userWallet = userWallet, cryptoCurrencyStatus = status) .conflate() .distinctUntilChanged() diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletExpressStatusesSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletExpressStatusesSubscriber.kt index fd21c385d1..8f46c558d4 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletExpressStatusesSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletExpressStatusesSubscriber.kt @@ -8,7 +8,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.onramp.GetOnrampTransactionsUseCase import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase import com.tangem.domain.onramp.model.cache.OnrampTransaction -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.wallets.models.UserWallet @@ -26,7 +26,7 @@ internal class SingleWalletExpressStatusesSubscriber( private val clickIntents: WalletClickIntents, private val analyticsEventHandler: AnalyticsEventHandler, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getOnrampTransactionsUseCase: GetOnrampTransactionsUseCase, private val onrampRemoveTransactionUseCase: OnrampRemoveTransactionUseCase, ) : WalletSubscriber() { @@ -35,7 +35,7 @@ internal class SingleWalletExpressStatusesSubscriber( coroutineScope: CoroutineScope, ): Flow, AppCurrency>> { return combine( - flow = getPrimaryCurrencyStatusUpdatesUseCase(userWalletId = userWallet.walletId) + flow = getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWalletId = userWallet.walletId) .conflate() .distinctUntilChanged(), flow2 = getSelectedAppCurrencyUseCase() diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt index ad67739b99..3058397289 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt @@ -5,7 +5,7 @@ import androidx.paging.cachedIn import androidx.paging.map import arrow.core.Either import com.tangem.domain.common.util.cardTypesResolver -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.domain.txhistory.models.TxHistoryListError @@ -35,14 +35,14 @@ internal class TxHistorySubscriber( private val isRefresh: Boolean, private val stateHolder: WalletStateController, private val clickIntents: WalletClickIntents, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase, private val txHistoryItemsUseCase: GetTxHistoryItemsUseCase, ) : WalletSubscriber() { override fun create(coroutineScope: CoroutineScope): Flow> { return flow { - getPrimaryCurrencyStatusUpdatesUseCase.collectLatest(userWalletId = userWallet.walletId) { status -> + getSingleCryptoCurrencyStatusUseCase.collectLatest(userWalletId = userWallet.walletId) { status -> val maybeTxHistoryItemCount = txHistoryItemsCountUseCase( userWalletId = userWallet.walletId, currency = status.currency, diff --git a/features/walletconnect/api/src/main/kotlin/com/tangem/features/walletconnect/components/WalletConnectEntryComponent.kt b/features/walletconnect/api/src/main/kotlin/com/tangem/features/walletconnect/components/WalletConnectEntryComponent.kt index c7d60d1091..2b584ceaae 100644 --- a/features/walletconnect/api/src/main/kotlin/com/tangem/features/walletconnect/components/WalletConnectEntryComponent.kt +++ b/features/walletconnect/api/src/main/kotlin/com/tangem/features/walletconnect/components/WalletConnectEntryComponent.kt @@ -2,7 +2,9 @@ package com.tangem.features.walletconnect.components import com.tangem.core.decompose.factory.ComponentFactory import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.wallets.models.UserWalletId interface WalletConnectEntryComponent : ComposableContentComponent { - interface Factory : ComponentFactory + data class Params(val userWalletId: UserWalletId) + interface Factory : ComponentFactory } \ No newline at end of file diff --git a/features/walletconnect/impl/build.gradle.kts b/features/walletconnect/impl/build.gradle.kts index 02b082fd94..77ae59129c 100644 --- a/features/walletconnect/impl/build.gradle.kts +++ b/features/walletconnect/impl/build.gradle.kts @@ -12,9 +12,8 @@ android { } dependencies { + implementation(projects.features.wallet.api) implementation(projects.features.walletconnect.api) - implementation(projects.domain.walletConnect) - implementation(projects.domain.walletConnect.models) /** Core */ implementation(projects.core.configToggles) @@ -24,13 +23,22 @@ dependencies { implementation(projects.common.ui) /** Domain models */ + implementation(projects.domain.appCurrency.models) + implementation(projects.domain.balanceHiding.models) implementation(projects.domain.blockaid.models) + implementation(projects.domain.models) implementation(projects.domain.qrScanning.models) implementation(projects.domain.tokens.models) implementation(projects.domain.wallets.models) + implementation(projects.domain.walletConnect) + implementation(projects.domain.walletConnect.models) /** Domain */ + implementation(projects.domain.appCurrency) + implementation(projects.domain.balanceHiding) implementation(projects.domain.qrScanning) + implementation(projects.domain.tokens) + implementation(projects.domain.wallets) /** DI */ implementation(deps.hilt.android) diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/ConnectionsComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/ConnectionsComponent.kt index 6c6a74e65a..45e927da97 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/ConnectionsComponent.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/ConnectionsComponent.kt @@ -13,15 +13,17 @@ import com.tangem.core.decompose.context.childByContext import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.ui.decompose.ComposableBottomSheetComponent import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.features.walletconnect.connections.model.WcConnectionsModel import com.tangem.features.walletconnect.connections.routes.WcConnectionsBottomSheetConfig import com.tangem.features.walletconnect.connections.ui.WcConnectionsContent internal class ConnectionsComponent( appComponentContext: AppComponentContext, + params: Params, ) : AppComponentContext by appComponentContext, ComposableContentComponent { - private val model: WcConnectionsModel = getOrCreateModel() + private val model: WcConnectionsModel = getOrCreateModel(params) private val bottomSheetSlot = childSlot( source = model.bottomSheetNavigation, serializer = null, @@ -52,4 +54,6 @@ internal class ConnectionsComponent( ) } } + + data class Params(val userWalletId: UserWalletId) } \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/DefaultWalletConnectEntryComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/DefaultWalletConnectEntryComponent.kt index 3f3ee812d0..f6cce51fd1 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/DefaultWalletConnectEntryComponent.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/DefaultWalletConnectEntryComponent.kt @@ -22,7 +22,7 @@ import dagger.assisted.AssistedInject @Suppress("UnusedPrivateMember") internal class DefaultWalletConnectEntryComponent @AssistedInject constructor( @Assisted private val appComponentContext: AppComponentContext, - @Assisted params: Unit, + @Assisted private val params: WalletConnectEntryComponent.Params, ) : AppComponentContext by appComponentContext, WalletConnectEntryComponent { private val contentNavigation = StackNavigation() @@ -47,12 +47,18 @@ internal class DefaultWalletConnectEntryComponent @AssistedInject constructor( config: ConnectionsInnerRoute, componentContext: ComponentContext, ): ComposableContentComponent = when (config) { - ConnectionsInnerRoute.Connections -> ConnectionsComponent(childByContext(componentContext)) + ConnectionsInnerRoute.Connections -> ConnectionsComponent( + appComponentContext = childByContext(componentContext), + params = ConnectionsComponent.Params(params.userWalletId), + ) ConnectionsInnerRoute.QrScan -> TODO("[REDACTED_JIRA]") } @AssistedFactory interface Factory : WalletConnectEntryComponent.Factory { - override fun create(context: AppComponentContext, params: Unit): DefaultWalletConnectEntryComponent + override fun create( + context: AppComponentContext, + params: WalletConnectEntryComponent.Params, + ): DefaultWalletConnectEntryComponent } } \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcAppInfoContainerComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcAppInfoContainerComponent.kt index bcfbcc79ea..be95b71cd3 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcAppInfoContainerComponent.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcAppInfoContainerComponent.kt @@ -1,13 +1,12 @@ package com.tangem.features.walletconnect.connections.components +import androidx.compose.animation.animateContentSize import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.extensions.compose.stack.Children -import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation import com.arkivanov.decompose.extensions.compose.subscribeAsState -import com.arkivanov.decompose.router.stack.StackNavigation import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.router.stack.pop import com.tangem.core.decompose.context.AppComponentContext @@ -18,8 +17,10 @@ import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.res.TangemTheme import com.tangem.domain.walletconnect.model.WcPairRequest +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.features.walletconnect.connections.model.WcAppInfoModel import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes import com.tangem.features.walletconnect.impl.R @@ -30,9 +31,8 @@ internal class WcAppInfoContainerComponent( ) : AppComponentContext by appComponentContext, ComposableContentComponent { private val model: WcAppInfoModel = getOrCreateModel(params = params) - private val contentNavigation = StackNavigation() private val contentStack = childStack( - source = contentNavigation, + source = model.contentNavigation, serializer = WcAppInfoRoutes.serializer(), initialConfiguration = WcAppInfoRoutes.AppInfo, childFactory = ::screenChild, @@ -51,10 +51,17 @@ internal class WcAppInfoContainerComponent( onDismissRequest = ::dismiss, content = content.active.configuration, ), - containerColor = TangemTheme.colors.background.tertiary, + onBack = ::contentBack, + containerColor = when (content.active.configuration) { + is WcAppInfoRoutes.Alert, + is WcAppInfoRoutes.SelectNetworks, + is WcAppInfoRoutes.AppInfo, + -> TangemTheme.colors.background.tertiary + is WcAppInfoRoutes.SelectWallet -> TangemTheme.colors.background.primary + }, title = { config -> Title(route = config) }, content = { - Children(stack = content, animation = stackAnimation()) { child -> + Children(modifier = Modifier.animateContentSize(), stack = content) { child -> child.instance.Content(modifier = Modifier) } }, @@ -64,7 +71,12 @@ internal class WcAppInfoContainerComponent( @Composable private fun Title(route: WcAppInfoRoutes) { TangemModalBottomSheetTitle( - title = resourceReference(R.string.wc_wallet_connect), + title = when (route) { + is WcAppInfoRoutes.Alert -> null + WcAppInfoRoutes.AppInfo -> resourceReference(R.string.wc_wallet_connect) + WcAppInfoRoutes.SelectNetworks -> TODO("[REDACTED_TASK_KEY]") + WcAppInfoRoutes.SelectWallet -> stringReference("Choose wallet") + }, startIconRes = when (route) { is WcAppInfoRoutes.AppInfo, is WcAppInfoRoutes.Alert -> null is WcAppInfoRoutes.SelectNetworks, is WcAppInfoRoutes.SelectWallet -> R.drawable.ic_back_24 @@ -88,19 +100,25 @@ internal class WcAppInfoContainerComponent( } private fun contentBack() { - contentNavigation.pop() + if (contentStack.value.active.configuration == WcAppInfoRoutes.AppInfo) { + dismiss() + } else { + model.contentNavigation.pop() + } } - private fun screenChild(config: WcAppInfoRoutes, componentContext: ComponentContext): ComposableContentComponent = - when (config) { - is WcAppInfoRoutes.AppInfo -> WcAppInfoComponent( - appComponentContext = childByContext(componentContext), - model = model, - ) + private fun screenChild(config: WcAppInfoRoutes, componentContext: ComponentContext): ComposableContentComponent { + val appComponentContext = childByContext(componentContext) + return when (config) { + is WcAppInfoRoutes.AppInfo -> WcAppInfoComponent(appComponentContext = appComponentContext, model = model) is WcAppInfoRoutes.Alert -> TODO() WcAppInfoRoutes.SelectNetworks -> TODO() - WcAppInfoRoutes.SelectWallet -> TODO() + WcAppInfoRoutes.SelectWallet -> WcSelectWalletComponent( + appComponentContext = appComponentContext, + model = model, + ) } + } - data class Params(val wcUrl: String, val source: WcPairRequest.Source) + data class Params(val userWalletId: UserWalletId, val wcUrl: String, val source: WcPairRequest.Source) } \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcSelectWalletComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcSelectWalletComponent.kt new file mode 100644 index 0000000000..d6c7e19964 --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcSelectWalletComponent.kt @@ -0,0 +1,130 @@ +package com.tangem.features.walletconnect.connections.components + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.key +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Devices +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastForEach +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.common.ui.userwallet.UserWalletItem +import com.tangem.common.ui.userwallet.state.UserWalletItemUM +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.ui.components.block.TangemBlockCardColors +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.features.walletconnect.connections.model.WcAppInfoModel +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf + +internal class WcSelectWalletComponent( + appComponentContext: AppComponentContext, + private val model: WcAppInfoModel, +) : AppComponentContext by appComponentContext, ComposableContentComponent { + + @Composable + override fun Content(modifier: Modifier) { + val walletsState by model.walletsUiState.collectAsStateWithLifecycle() + WcSelectWalletContent( + modifier = modifier.padding(start = 16.dp, end = 16.dp, bottom = 16.dp), + wallets = walletsState.wallets, + selectedWalletId = walletsState.selectedUserWallet.walletId, + ) + } +} + +@Composable +private fun WcSelectWalletContent( + wallets: ImmutableList, + selectedWalletId: UserWalletId, + modifier: Modifier = Modifier, +) { + Column(modifier = modifier) { + wallets.fastForEach { state -> + key(state.id) { + val baseModifier = Modifier + .clip(RoundedCornerShape(14.dp)) + .clickable(onClick = state.onClick) + val itemModifier = if (state.id == selectedWalletId) { + baseModifier.border( + width = 1.dp, + color = TangemTheme.colors.text.accent, + shape = RoundedCornerShape(14.dp), + ) + } else { + baseModifier + } + UserWalletItem( + modifier = itemModifier, + state = state, + blockColors = TangemBlockCardColors.copy( + containerColor = Color.Unspecified, + disabledContainerColor = Color.Unspecified, + ), + ) + } + } + } +} + +@Composable +@Preview(showBackground = true, device = Devices.PIXEL_7_PRO) +@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES) +private fun WcSelectWalletContent_Preview() { + TangemThemePreview { + WcSelectWalletContent( + modifier = Modifier + .background(TangemTheme.colors.background.tertiary) + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp), + selectedWalletId = UserWalletId("user_wallet_1".encodeToByteArray()), + wallets = persistentListOf( + UserWalletItemUM( + id = UserWalletId("user_wallet_1".encodeToByteArray()), + name = stringReference("Tangem 2.0"), + information = stringReference("42 tokens"), + balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false), + isEnabled = true, + onClick = {}, + ), + UserWalletItemUM( + id = UserWalletId("user_wallet_2".encodeToByteArray()), + name = stringReference("Tangem White"), + information = stringReference("24 tokens"), + balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false), + isEnabled = true, + onClick = {}, + ), + UserWalletItemUM( + id = UserWalletId("user_wallet_3".encodeToByteArray()), + name = stringReference("Bitcoin"), + information = stringReference("1 token"), + balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false), + isEnabled = true, + onClick = {}, + ), + UserWalletItemUM( + id = UserWalletId("user_wallet_4".encodeToByteArray()), + name = stringReference("Tangem 1.0"), + information = stringReference("21 tokens"), + balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false), + isEnabled = true, + onClick = {}, + ), + ), + ) + } +} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcAppInfoUM.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcAppInfoUM.kt index f7d17a2af5..92e385a3fa 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcAppInfoUM.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcAppInfoUM.kt @@ -26,6 +26,7 @@ internal sealed class WcAppInfoUM : TangemBottomSheetConfigContent { val appSubtitle: String, val notification: WcAppInfoSecurityNotification?, val walletName: String, + val onWalletClick: () -> Unit, val networksInfo: WcNetworksInfo, override val connectButtonConfig: WcPrimaryButtonConfig, override val onDismiss: () -> Unit, diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcAppInfoWalletUM.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcAppInfoWalletUM.kt new file mode 100644 index 0000000000..0c682702a0 --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcAppInfoWalletUM.kt @@ -0,0 +1,10 @@ +package com.tangem.features.walletconnect.connections.entity + +import com.tangem.common.ui.userwallet.state.UserWalletItemUM +import com.tangem.domain.wallets.models.UserWallet +import kotlinx.collections.immutable.ImmutableList + +internal data class WcAppInfoWalletUM( + val wallets: ImmutableList, + val selectedUserWallet: UserWallet, +) \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcAppInfoModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcAppInfoModel.kt index 3a6e4520ba..fe9348ef4d 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcAppInfoModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcAppInfoModel.kt @@ -1,47 +1,98 @@ package com.tangem.features.walletconnect.connections.model import androidx.compose.runtime.Stable +import com.arkivanov.decompose.router.stack.StackNavigation +import com.arkivanov.decompose.router.stack.pop +import com.arkivanov.decompose.router.stack.pushNew +import com.tangem.common.ui.userwallet.state.UserWalletItemUM import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router +import com.tangem.core.decompose.ui.UiMessageSender +import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase +import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase +import com.tangem.domain.tokens.GetWalletTotalBalanceUseCase import com.tangem.domain.walletconnect.model.WcPairRequest import com.tangem.domain.walletconnect.model.WcSessionApprove import com.tangem.domain.walletconnect.model.WcSessionProposal import com.tangem.domain.walletconnect.usecase.pair.WcPairState import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.domain.wallets.usecase.GetCardImageUseCase +import com.tangem.domain.wallets.usecase.GetWalletsUseCase import com.tangem.features.walletconnect.connections.components.WcAppInfoContainerComponent import com.tangem.features.walletconnect.connections.entity.WcAppInfoUM +import com.tangem.features.walletconnect.connections.entity.WcAppInfoWalletUM import com.tangem.features.walletconnect.connections.entity.WcPrimaryButtonConfig import com.tangem.features.walletconnect.connections.model.transformers.WcAppInfoTransformer +import com.tangem.features.walletconnect.connections.model.transformers.WcAppInfoWalletChangedTransformer import com.tangem.features.walletconnect.connections.model.transformers.WcConnectButtonProgressTransformer +import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes +import com.tangem.features.walletconnect.connections.utils.WcUserWalletsFetcher import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.flow.* import javax.inject.Inject import kotlin.properties.Delegates import com.tangem.utils.transformer.update as transformerUpdate +@Suppress("LongParameterList") @Stable @ModelScoped internal class WcAppInfoModel @Inject constructor( + private val router: Router, override val dispatchers: CoroutineDispatcherProvider, wcPairUseCaseFactory: WcPairUseCase.Factory, - private val router: Router, + getWalletsUseCase: GetWalletsUseCase, + getWalletTotalBalanceUseCase: GetWalletTotalBalanceUseCase, + getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, + getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, + messageSender: UiMessageSender, + getCardImageUseCase: GetCardImageUseCase, paramsContainer: ParamsContainer, ) : Model() { private val params: WcAppInfoContainerComponent.Params = paramsContainer.require() - private val wcPairUseCase = wcPairUseCaseFactory.create(WcPairRequest(uri = params.wcUrl, source = params.source)) + private val wcPairUseCase = wcPairUseCaseFactory.create( + WcPairRequest( + userWalletId = params.userWalletId, + uri = params.wcUrl, + source = params.source, + ), + ) + private val userWalletsFetcher = WcUserWalletsFetcher( + getWalletsUseCase = getWalletsUseCase, + getWalletTotalBalanceUseCase = getWalletTotalBalanceUseCase, + getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, + getBalanceHidingSettingsUseCase = getBalanceHidingSettingsUseCase, + messageSender = messageSender, + getCardImageUseCase = getCardImageUseCase, + onWalletSelected = ::onWalletSelected, + ) + + private val selectedUserWalletFlow = + MutableStateFlow(getWalletsUseCase.invokeSync().first { it.walletId == params.userWalletId }) + // TODO(wc) Doston: Temp solution, will be fixed in next PR`s + private var proposalNetwork by Delegates.notNull() + internal var sessionProposal by Delegates.notNull() + + // UI states + internal val contentNavigation = StackNavigation() val appInfoUiState: StateFlow field = MutableStateFlow(createLoadingState()) - - // TODO(wc) Doston: Temp solution, will be fixed in next PR`s - private var userWallet by Delegates.notNull() - private var proposalNetwork by Delegates.notNull() + val walletsUiState: StateFlow + field = MutableStateFlow(WcAppInfoWalletUM(persistentListOf(), selectedUserWalletFlow.value)) init { loadDAppInfo() + combine( + flow = userWalletsFetcher.userWallets, + flow2 = selectedUserWalletFlow, + transform = ::updateWalletsState, + ).launchIn(modelScope) } private fun loadDAppInfo() { @@ -62,14 +113,15 @@ internal class WcAppInfoModel @Inject constructor( } is WcPairState.Loading -> appInfoUiState.update { createLoadingState() } is WcPairState.Proposal -> { - userWallet = state.dAppSession.proposalNetwork.keys.first { !it.isLocked } - proposalNetwork = state.dAppSession.proposalNetwork.getValue(userWallet) + sessionProposal = state.dAppSession + proposalNetwork = sessionProposal.proposalNetwork.getValue(selectedUserWalletFlow.value) appInfoUiState.transformerUpdate( WcAppInfoTransformer( dAppSession = state.dAppSession, onDismiss = ::dismiss, onConnect = ::onConnect, - userWallet = userWallet, + onWalletClick = { contentNavigation.pushNew(WcAppInfoRoutes.SelectWallet) }, + userWallet = selectedUserWalletFlow.value, proposalNetwork = proposalNetwork, ), ) @@ -87,13 +139,24 @@ internal class WcAppInfoModel @Inject constructor( private fun onConnect() { wcPairUseCase.approve( WcSessionApprove( - wallet = userWallet, - network = - proposalNetwork.required.plus(proposalNetwork.available).toList(), + wallet = selectedUserWalletFlow.value, + network = proposalNetwork.required.plus(proposalNetwork.available).toList(), ), ) } + private fun onWalletSelected(userWalletId: UserWalletId) { + val selectedUserWallet = sessionProposal.proposalNetwork.keys.first { it.walletId == userWalletId } + selectedUserWalletFlow.update { selectedUserWallet } + proposalNetwork = sessionProposal.proposalNetwork.getValue(selectedUserWallet) + appInfoUiState.transformerUpdate(WcAppInfoWalletChangedTransformer(selectedUserWallet, proposalNetwork)) + contentNavigation.pop() + } + + private fun updateWalletsState(items: ImmutableList, userWallet: UserWallet) { + walletsUiState.update { state -> state.copy(wallets = items, selectedUserWallet = userWallet) } + } + private fun createLoadingState(): WcAppInfoUM.Loading { return WcAppInfoUM.Loading( onDismiss = ::dismiss, diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectedAppInfoModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectedAppInfoModel.kt index 6126b5f404..a751963826 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectedAppInfoModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectedAppInfoModel.kt @@ -6,6 +6,7 @@ import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender +import com.tangem.core.ui.extensions.iconResId import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.message.SnackbarMessage import com.tangem.domain.walletconnect.model.WcSession @@ -13,9 +14,10 @@ import com.tangem.domain.walletconnect.usecase.WcSessionsUseCase import com.tangem.domain.walletconnect.usecase.disconnect.WcDisconnectUseCase import com.tangem.features.walletconnect.connections.components.WcConnectedAppInfoComponent import com.tangem.features.walletconnect.connections.entity.WcConnectedAppInfoUM +import com.tangem.features.walletconnect.connections.entity.WcNetworkInfoItem import com.tangem.features.walletconnect.connections.entity.WcPrimaryButtonConfig import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update @@ -56,7 +58,15 @@ internal class WcConnectedAppInfoModel @Inject constructor( isVerified = session.securityStatus == CheckDAppResult.SAFE, appSubtitle = session.sdkModel.appMetaData.description, walletName = session.wallet.name, - networks = persistentListOf(), // TODO(wc): Nikolai & Doston: Where to find networks??? + networks = session.networks + .map { + WcNetworkInfoItem( + id = it.id.value, + icon = it.iconResId, + name = it.name, + symbol = it.currencySymbol, + ) + }.toImmutableList(), disconnectButtonConfig = WcPrimaryButtonConfig( showProgress = false, enabled = true, diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectionsModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectionsModel.kt index 49062a9de9..96d5df7e28 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectionsModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectionsModel.kt @@ -6,6 +6,7 @@ import com.arkivanov.decompose.router.slot.activate import com.tangem.common.routing.AppRoute import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM @@ -16,11 +17,12 @@ import com.tangem.core.ui.message.EventMessageAction import com.tangem.core.ui.res.TangemTheme import com.tangem.domain.qrscanning.models.SourceType import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase -import com.tangem.domain.walletconnect.model.WcSession import com.tangem.domain.walletconnect.WcPairService import com.tangem.domain.walletconnect.model.WcPairRequest +import com.tangem.domain.walletconnect.model.WcSession import com.tangem.domain.walletconnect.usecase.WcSessionsUseCase import com.tangem.domain.walletconnect.usecase.disconnect.WcDisconnectUseCase +import com.tangem.features.walletconnect.connections.components.ConnectionsComponent import com.tangem.features.walletconnect.connections.entity.WcConnectionsState import com.tangem.features.walletconnect.connections.entity.WcConnectionsTopAppBarConfig import com.tangem.features.walletconnect.connections.model.transformers.WcSessionsTransformer @@ -44,8 +46,10 @@ internal class WcConnectionsModel @Inject constructor( private val wcDisconnectUseCase: WcDisconnectUseCase, private val wcPairService: WcPairService, override val dispatchers: CoroutineDispatcherProvider, + paramsContainer: ParamsContainer, ) : Model() { + private val params = paramsContainer.require() val uiState: StateFlow field = MutableStateFlow(getInitialState()) val bottomSheetNavigation: SlotNavigation = SlotNavigation() @@ -58,7 +62,15 @@ internal class WcConnectionsModel @Inject constructor( private fun listenQrUpdates() { listenToQrScanningUseCase(SourceType.WALLET_CONNECT) .getOrElse { emptyFlow() } - .onEach { wcUrl -> wcPairService.pair(WcPairRequest(wcUrl, WcPairRequest.Source.QR)) } + .onEach { wcUrl -> + wcPairService.pair( + WcPairRequest( + userWalletId = params.userWalletId, + uri = wcUrl, + source = WcPairRequest.Source.QR, + ), + ) + } .launchIn(modelScope) } diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoTransformer.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoTransformer.kt index 134338c410..2249504df5 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoTransformer.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoTransformer.kt @@ -1,17 +1,16 @@ package com.tangem.features.walletconnect.connections.model.transformers import com.domain.blockaid.models.dapp.CheckDAppResult -import com.tangem.core.ui.extensions.iconResId import com.tangem.domain.walletconnect.model.WcSessionProposal import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.walletconnect.connections.entity.* import com.tangem.utils.transformer.Transformer -import kotlinx.collections.immutable.toImmutableList internal class WcAppInfoTransformer( private val dAppSession: WcSessionProposal, private val onDismiss: () -> Unit, private val onConnect: () -> Unit, + private val onWalletClick: () -> Unit, private val userWallet: UserWallet, private val proposalNetwork: WcSessionProposal.ProposalNetwork, ) : Transformer { @@ -24,7 +23,8 @@ internal class WcAppInfoTransformer( appSubtitle = dAppSession.dAppMetaData.description, notification = createNotification(dAppSession.securityStatus), walletName = userWallet.name, - networksInfo = convertNetworksInfo(proposalNetwork), + onWalletClick = onWalletClick, + networksInfo = WcNetworksInfoConverter.convert(proposalNetwork), connectButtonConfig = WcPrimaryButtonConfig( showProgress = false, enabled = proposalNetwork.missingRequired.isEmpty(), @@ -41,26 +41,4 @@ internal class WcAppInfoTransformer( CheckDAppResult.FAILED_TO_VERIFY -> WcAppInfoSecurityNotification.UnknownDomain } } - - private fun convertNetworksInfo(proposalNetwork: WcSessionProposal.ProposalNetwork): WcNetworksInfo { - return if (proposalNetwork.missingRequired.isNotEmpty()) { - WcNetworksInfo.MissingRequiredNetworkInfo( - networks = proposalNetwork.missingRequired - .joinToString { it.name }, - ) - } else { - WcNetworksInfo.ContainsAllRequiredNetworks( - items = (proposalNetwork.required + proposalNetwork.available) - .map { - WcNetworkInfoItem( - id = it.id.value, - icon = it.iconResId, - name = it.name, - symbol = it.currencySymbol, - ) - } - .toImmutableList(), - ) - } - } } \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoWalletChangedTransformer.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoWalletChangedTransformer.kt new file mode 100644 index 0000000000..453ab9b608 --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoWalletChangedTransformer.kt @@ -0,0 +1,22 @@ +package com.tangem.features.walletconnect.connections.model.transformers + +import com.tangem.domain.walletconnect.model.WcSessionProposal +import com.tangem.domain.wallets.models.UserWallet +import com.tangem.features.walletconnect.connections.entity.WcAppInfoUM +import com.tangem.utils.transformer.Transformer + +internal class WcAppInfoWalletChangedTransformer( + private val selectedUserWallet: UserWallet, + private val proposalNetwork: WcSessionProposal.ProposalNetwork, +) : Transformer { + override fun transform(prevState: WcAppInfoUM): WcAppInfoUM { + val contentState = prevState as? WcAppInfoUM.Content ?: return prevState + return contentState.copy( + walletName = selectedUserWallet.name, + networksInfo = WcNetworksInfoConverter.convert(proposalNetwork), + connectButtonConfig = prevState.connectButtonConfig.copy( + enabled = proposalNetwork.missingRequired.isEmpty(), + ), + ) + } +} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcNetworksInfoConverter.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcNetworksInfoConverter.kt new file mode 100644 index 0000000000..8bf63c01cf --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcNetworksInfoConverter.kt @@ -0,0 +1,32 @@ +package com.tangem.features.walletconnect.connections.model.transformers + +import com.tangem.core.ui.extensions.iconResId +import com.tangem.domain.walletconnect.model.WcSessionProposal +import com.tangem.features.walletconnect.connections.entity.WcNetworkInfoItem +import com.tangem.features.walletconnect.connections.entity.WcNetworksInfo +import com.tangem.utils.converter.Converter +import kotlinx.collections.immutable.toImmutableList + +internal object WcNetworksInfoConverter : Converter { + override fun convert(value: WcSessionProposal.ProposalNetwork): WcNetworksInfo { + return if (value.missingRequired.isNotEmpty()) { + WcNetworksInfo.MissingRequiredNetworkInfo( + networks = value.missingRequired + .joinToString { it.name }, + ) + } else { + WcNetworksInfo.ContainsAllRequiredNetworks( + items = (value.required + value.available) + .map { + WcNetworkInfoItem( + id = it.id.value, + icon = it.iconResId, + name = it.name, + symbol = it.currencySymbol, + ) + } + .toImmutableList(), + ) + } + } +} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/DefaultWcRoutingComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/DefaultWcRoutingComponent.kt index cfe15122ed..45ccb328ab 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/DefaultWcRoutingComponent.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/DefaultWcRoutingComponent.kt @@ -16,7 +16,7 @@ import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.features.walletconnect.components.WcRoutingComponent import com.tangem.features.walletconnect.connections.components.WcAppInfoContainerComponent -import com.tangem.features.walletconnect.transaction.components.WcSignTransactionComponent +import com.tangem.features.walletconnect.transaction.components.WcSignTransactionContainerComponent import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -55,13 +55,17 @@ internal class DefaultWcRoutingComponent @AssistedInject constructor( router = model.innerRouter, ) return when (config) { - is WcInnerRoute.SignMessage -> WcSignTransactionComponent( + is WcInnerRoute.SignMessage -> WcSignTransactionContainerComponent( childContext, - params = WcSignTransactionComponent.Params(config.rawRequest), + params = WcSignTransactionContainerComponent.Params(config.rawRequest), ) is WcInnerRoute.Pair -> WcAppInfoContainerComponent( childContext, - WcAppInfoContainerComponent.Params(config.request.uri, config.request.source), + WcAppInfoContainerComponent.Params( + userWalletId = config.request.userWalletId, + wcUrl = config.request.uri, + source = config.request.source, + ), ) } } diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoContent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoContent.kt index f248d6323c..136d5ac26b 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoContent.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoContent.kt @@ -220,7 +220,12 @@ private fun WcAppInfoSecondBlock(state: WcAppInfoUM.Content, modifier: Modifier val itemsModifier = Modifier .fillMaxWidth() .padding(TangemTheme.dimens.spacing12) - WalletRowItem(modifier = itemsModifier, walletName = state.walletName) + WalletRowItem( + modifier = Modifier + .clickable(onClick = state.onWalletClick) + .then(itemsModifier), + walletName = state.walletName, + ) HorizontalDivider(thickness = 1.dp, color = TangemTheme.colors.stroke.primary) SelectNetworksBlock( networksInfo = state.networksInfo, @@ -565,6 +570,7 @@ private class WcAppInfoStateProvider : CollectionPreviewParameterProvider Unit, +) { + + private var loadedArtworks: HashMap = hashMapOf() + + @OptIn(ExperimentalCoroutinesApi::class) + val userWallets: Flow> = getWalletsUseCase().transformLatest { wallets -> + val uiModels = UserWalletItemUMConverter(onClick = onWalletSelected) + .convertList(wallets) + .toImmutableList() + + emit(uiModels) + combine( + flow = getSelectedAppCurrencyUseCase().distinctUntilChanged(), + flow2 = getBalanceHidingSettingsUseCase().distinctUntilChanged(), + flow3 = getWalletTotalBalanceUseCase(wallets.map(UserWallet::walletId)).distinctUntilChanged(), + flow4 = loadArtworks(wallets), + ) { maybeAppCurrency, balanceHidingSettings, maybeBalances, artworks -> + val models = createUiModels( + wallets = wallets, + maybeAppCurrency = maybeAppCurrency, + maybeBalances = maybeBalances, + balanceHidingSettings = balanceHidingSettings, + artworks = artworks, + ).getOrElse( + ifLoading = { return@combine }, + ifError = { + val message = resourceReference(R.string.common_unknown_error) + messageSender.send(SnackbarMessage(message)) + + return@combine + }, + ) + + emit(models) + }.collect() + } + + private fun loadArtworks(wallets: List): Flow> { + return flow { + emit(hashMapOf()) // emits right away so the transform doesn't wait for the images' loading to finish + wallets.forEach { wallet -> + val card = wallet.scanResponse.card + val artwork = getCardImageUseCase( + cardId = wallet.cardId, + cardPublicKey = card.cardPublicKey, + size = ArtworkSize.SMALL, + manufacturerName = card.manufacturer.name, + firmwareVersion = card.firmwareVersion.toSdkFirmwareVersion(), + ) + loadedArtworks[wallet.walletId] = artwork + emit(loadedArtworks) + } + } + } + + private fun createUiModels( + wallets: List, + maybeAppCurrency: Either, + maybeBalances: Lce>, + balanceHidingSettings: BalanceHidingSettings, + artworks: HashMap, + ): Lce> = lce { + val balances = withError( + transform = { Error.UnableToGetBalances }, + block = { + maybeBalances.bindOrNull().orEmpty() + .filterKeys { userWalletId -> wallets.any { it.walletId == userWalletId } } + .mapKeys { entry -> wallets.first { it.walletId == entry.key } } + }, + ) + + val appCurrency = withError( + transform = { Error.UnableToGetAppCurrency }, + block = { maybeAppCurrency.toLce().bind() }, + ) + + balances + .map { (userWallet, balance) -> + UserWalletItemUMConverter( + onClick = onWalletSelected, + appCurrency = appCurrency, + balance = balance, + isBalanceHidden = balanceHidingSettings.isBalanceHidden, + artwork = artworks[userWallet.walletId], + ) + .convert(userWallet) + } + .toImmutableList() + } + + sealed class Error { + + data object UnableToGetAppCurrency : Error() + + data object UnableToGetBalances : Error() + } +} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionComponent.kt index 9ec9f43b8f..9ffe0a28d5 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionComponent.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionComponent.kt @@ -1,37 +1,28 @@ package com.tangem.features.walletconnect.transaction.components import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.tangem.core.decompose.context.AppComponentContext -import com.tangem.core.decompose.model.getOrCreateModel -import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.decompose.ComposableContentComponent -import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest import com.tangem.features.walletconnect.transaction.model.WcSignTransactionModel -import com.tangem.features.walletconnect.transaction.ui.sign.WcSignTransactionModalBottomSheet +import com.tangem.features.walletconnect.transaction.ui.sign.WcSignTransactionModalBottomSheetContent internal class WcSignTransactionComponent( - appComponentContext: AppComponentContext, - params: Params, + private val appComponentContext: AppComponentContext, + private val model: WcSignTransactionModel, + private val transactionInfoOnClick: () -> Unit, ) : AppComponentContext by appComponentContext, ComposableContentComponent { - private val model: WcSignTransactionModel = getOrCreateModel(params) - @Composable override fun Content(modifier: Modifier) { - val content by model.uiState.collectAsStateWithLifecycle() - content?.let { - WcSignTransactionModalBottomSheet( - config = TangemBottomSheetConfig( - isShown = true, - onDismissRequest = it.actions.onDismiss, - content = it, - ), + val content = model.uiState.collectAsStateWithLifecycle().value + + if (content != null) { + WcSignTransactionModalBottomSheetContent( + state = content, + onClickTransactionRequest = transactionInfoOnClick, ) } } - - data class Params(val rawRequest: WcSdkSessionRequest) } \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionContainerComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionContainerComponent.kt new file mode 100644 index 0000000000..7bfc3e7738 --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionContainerComponent.kt @@ -0,0 +1,123 @@ +package com.tangem.features.walletconnect.transaction.components + +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import com.arkivanov.decompose.ComponentContext +import com.arkivanov.decompose.extensions.compose.stack.Children +import com.arkivanov.decompose.extensions.compose.subscribeAsState +import com.arkivanov.decompose.router.stack.StackNavigation +import com.arkivanov.decompose.router.stack.childStack +import com.arkivanov.decompose.router.stack.navigate +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.context.childByContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet +import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.res.TangemTheme +import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest +import com.tangem.features.walletconnect.impl.R +import com.tangem.features.walletconnect.transaction.model.WcSignTransactionModel +import com.tangem.features.walletconnect.transaction.routes.WcSignTransactionRoutes + +internal class WcSignTransactionContainerComponent( + private val appComponentContext: AppComponentContext, + params: Params, +) : AppComponentContext by appComponentContext, ComposableContentComponent { + + private val model: WcSignTransactionModel = getOrCreateModel(params = params) + private val contentNavigation = StackNavigation() + private val contentStack = childStack( + source = contentNavigation, + serializer = WcSignTransactionRoutes.serializer(), + initialConfiguration = WcSignTransactionRoutes.Transaction, + childFactory = ::screenChild, + ) + + private fun dismiss() { + model.dismiss() + } + + @Composable + override fun Content(modifier: Modifier) { + val content by contentStack.subscribeAsState() + TangemModalBottomSheet( + config = TangemBottomSheetConfig( + isShown = true, + onDismissRequest = ::dismiss, + content = content.active.configuration, + ), + containerColor = TangemTheme.colors.background.tertiary, + title = { config -> Title(route = config) }, + content = { + Box( + modifier = Modifier + .fillMaxWidth() + .animateContentSize(), + ) { + Children(stack = content) { child -> + child.instance.Content(modifier = Modifier) + } + } + }, + ) + } + + @Composable + private fun Title(route: WcSignTransactionRoutes) { + TangemModalBottomSheetTitle( + title = resourceReference(R.string.wc_wallet_connect), + startIconRes = when (route) { + is WcSignTransactionRoutes.Transaction -> null + else -> R.drawable.ic_back_24 + }, + onStartClick = when (route) { + is WcSignTransactionRoutes.Transaction -> null + else -> ::toTransaction + }, + endIconRes = when (route) { + is WcSignTransactionRoutes.Transaction -> R.drawable.ic_close_24 + else -> null + }, + onEndClick = when (route) { + is WcSignTransactionRoutes.Transaction -> ::dismiss + else -> null + }, + ) + } + + private fun toTransactionRequestInfo() { + contentNavigation.navigate { + listOf(WcSignTransactionRoutes.TransactionRequestInfo) + } + } + + private fun toTransaction() { + contentNavigation.navigate { + listOf(WcSignTransactionRoutes.Transaction) + } + } + + private fun screenChild( + config: WcSignTransactionRoutes, + componentContext: ComponentContext, + ): ComposableContentComponent = when (config) { + is WcSignTransactionRoutes.Transaction -> WcSignTransactionComponent( + appComponentContext = childByContext(componentContext), + model = model, + transactionInfoOnClick = ::toTransactionRequestInfo, + ) + is WcSignTransactionRoutes.TransactionRequestInfo -> WcSignTransactionRequestInfoComponent( + appComponentContext = childByContext(componentContext), + model = model, + ) + } + + data class Params(val rawRequest: WcSdkSessionRequest) +} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionRequestInfoComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionRequestInfoComponent.kt new file mode 100644 index 0000000000..7563b8a646 --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionRequestInfoComponent.kt @@ -0,0 +1,24 @@ +package com.tangem.features.walletconnect.transaction.components + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.features.walletconnect.transaction.model.WcSignTransactionModel +import com.tangem.features.walletconnect.transaction.ui.common.TransactionRequestInfoContent + +internal class WcSignTransactionRequestInfoComponent( + private val appComponentContext: AppComponentContext, + private val model: WcSignTransactionModel, +) : AppComponentContext by appComponentContext, ComposableContentComponent { + + @Composable + override fun Content(modifier: Modifier) { + val content = model.uiState.collectAsStateWithLifecycle().value + + if (content != null) { + TransactionRequestInfoContent(content) + } + } +} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/WcSignTransactionUM.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/WcSignTransactionUM.kt new file mode 100644 index 0000000000..77379d44e1 --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/WcSignTransactionUM.kt @@ -0,0 +1,56 @@ +package com.tangem.features.walletconnect.transaction.entity + +import androidx.annotation.DrawableRes +import androidx.compose.runtime.Immutable +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent +import com.tangem.core.ui.extensions.TextReference +import kotlinx.collections.immutable.ImmutableList + +@Immutable +internal data class WcSignTransactionUM( + val actions: WcTransactionActionsUM, + val transaction: WcTransactionUM, + val transactionRequestInfo: WcTransactionRequestInfoUM, +) : TangemBottomSheetConfigContent + +@Immutable +internal data class WcTransactionUM( + val appName: String, + val appIcon: String, + val isVerified: Boolean, + val appSubtitle: String, + val walletName: String, + val networkInfo: WcNetworkInfoUM, + val addressText: String? = null, + val networkFee: String? = null, + val isLoading: Boolean = false, +) + +@Immutable +internal data class WcTransactionRequestInfoUM( + val blocks: ImmutableList, +) + +@Immutable +internal data class WcTransactionRequestBlockUM( + val info: ImmutableList, +) + +@Immutable +internal data class WcTransactionRequestInfoItemUM( + val title: TextReference, + val description: String = "", +) + +@Immutable +internal data class WcTransactionActionsUM( + val onDismiss: () -> Unit, + val onSign: () -> Unit, + val onCopy: () -> Unit, +) + +@Immutable +internal data class WcNetworkInfoUM( + val name: String, + @DrawableRes val iconRes: Int, +) \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt index 68343c308e..ed6ea36064 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt @@ -10,9 +10,9 @@ import com.tangem.domain.walletconnect.WcRequestUseCaseFactory import com.tangem.domain.walletconnect.usecase.method.WcSignState import com.tangem.domain.walletconnect.usecase.method.WcSignStep import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase -import com.tangem.features.walletconnect.transaction.components.WcSignTransactionComponent -import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionUM -import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM +import com.tangem.features.walletconnect.transaction.components.WcSignTransactionContainerComponent +import com.tangem.features.walletconnect.transaction.entity.WcSignTransactionUM +import com.tangem.features.walletconnect.transaction.entity.WcTransactionActionsUM import com.tangem.features.walletconnect.transaction.utils.toUM import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableStateFlow @@ -35,7 +35,7 @@ internal class WcSignTransactionModel @Inject constructor( private val _uiState = MutableStateFlow(null) val uiState: StateFlow = _uiState - private val params = paramsContainer.require() + private val params = paramsContainer.require() init { modelScope.launch { @@ -47,10 +47,8 @@ internal class WcSignTransactionModel @Inject constructor( signState = signState, actions = WcTransactionActionsUM( onDismiss = { cancel(useCase) }, - onBack = ::showTransactionState, - activeButtonOnClick = useCase::sign, + onSign = useCase::sign, onCopy = { copyData(useCase.rawSdkRequest.request.params) }, - transactionRequestOnClick = ::showTransactionRequestState, ), ) _uiState.emit(signTransactionUM) @@ -59,6 +57,10 @@ internal class WcSignTransactionModel @Inject constructor( } } + fun dismiss() { + _uiState.value?.actions?.onDismiss?.invoke() ?: router.pop() + } + private fun signingIsDone(signState: WcSignState<*>): Boolean { (signState.domainStep as? WcSignStep.Result)?.result?.let { router.pop() @@ -75,12 +77,4 @@ internal class WcSignTransactionModel @Inject constructor( private fun copyData(text: String) { clipboardManager.setText(text = text, isSensitive = true) } - - private fun showTransactionRequestState() { - _uiState.value = _uiState.value?.copy(state = WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO) - } - - private fun showTransactionState() { - _uiState.value = _uiState.value?.copy(state = WcSignTransactionUM.State.TRANSACTION) - } } \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/routes/WcSignTransactionRoutes.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/routes/WcSignTransactionRoutes.kt new file mode 100644 index 0000000000..6c5c1d9fa8 --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/routes/WcSignTransactionRoutes.kt @@ -0,0 +1,15 @@ +package com.tangem.features.walletconnect.transaction.routes + +import androidx.compose.runtime.Immutable +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent +import kotlinx.serialization.Serializable + +@Serializable +@Immutable +internal sealed class WcSignTransactionRoutes : TangemBottomSheetConfigContent { + @Serializable + data object Transaction : WcSignTransactionRoutes() + + @Serializable + data object TransactionRequestInfo : WcSignTransactionRoutes() +} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/TransactionRequestInfoContent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/TransactionRequestInfoContent.kt new file mode 100644 index 0000000000..382da28e98 --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/TransactionRequestInfoContent.kt @@ -0,0 +1,219 @@ +package com.tangem.features.walletconnect.transaction.ui.common + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.tooling.preview.Devices +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.components.SecondaryButtonIconEnd +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet +import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle +import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.walletconnect.impl.R +import com.tangem.features.walletconnect.transaction.entity.* +import com.tangem.features.walletconnect.transaction.entity.WcNetworkInfoUM +import com.tangem.features.walletconnect.transaction.entity.WcSignTransactionUM +import com.tangem.features.walletconnect.transaction.entity.WcTransactionActionsUM +import com.tangem.features.walletconnect.transaction.entity.WcTransactionRequestInfoUM +import com.tangem.features.walletconnect.transaction.entity.WcTransactionUM +import kotlinx.collections.immutable.persistentListOf + +private const val MIN_HEIGHT_SCREEN_PERCENT = 0.35f +private const val MAX_HEIGHT_SCREEN_PERCENT = 0.75f + +@Composable +internal fun TransactionRequestInfoContent(state: WcSignTransactionUM) { + val screenHeight = LocalConfiguration.current.screenHeightDp + val minHeight = (screenHeight * MIN_HEIGHT_SCREEN_PERCENT).dp + val maxHeight = (screenHeight * MAX_HEIGHT_SCREEN_PERCENT).dp + + Box( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = minHeight, max = maxHeight) + .padding(horizontal = TangemTheme.dimens.spacing16), + ) { + LazyColumn( + modifier = Modifier + .fillMaxWidth(), + contentPadding = PaddingValues(top = TangemTheme.dimens.spacing8, bottom = TangemTheme.dimens.spacing70), + ) { + items(state.transactionRequestInfo.blocks) { block -> + Column( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(TangemTheme.dimens.radius16)) + .background(TangemTheme.colors.background.action) + .padding( + start = TangemTheme.dimens.spacing16, + end = TangemTheme.dimens.spacing16, + top = TangemTheme.dimens.spacing20, + ), + ) { + block.info.forEach { item -> + Text( + text = item.title.resolveReference(), + style = TangemTheme.typography.subtitle2, + color = TangemTheme.colors.text.tertiary, + ) + if (item.description.isNotEmpty()) { + Text( + text = item.description, + modifier = Modifier.padding( + top = TangemTheme.dimens.spacing4, + bottom = TangemTheme.dimens.spacing20, + ), + style = TangemTheme.typography.body2, + color = TangemTheme.colors.text.primary1, + ) + } else { + Spacer(modifier = Modifier.size(TangemTheme.dimens.size12)) + } + } + } + Spacer(modifier = Modifier.size(TangemTheme.dimens.size20)) + } + } + + SecondaryButtonIconEnd( + modifier = Modifier + .align(Alignment.BottomCenter) + .padding(bottom = TangemTheme.dimens.spacing20) + .fillMaxWidth(), + text = stringResourceSafe(R.string.wc_copy_data_button_text), + onClick = state.actions.onCopy, + iconResId = R.drawable.ic_copy_24, + ) + } +} + +@Composable +@Preview(showBackground = true, device = Devices.PIXEL_7_PRO) +@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES) +private fun WcSignTransactionRequestInfoBottomSheetPreview( + @PreviewParameter(WcSignTransactionStateProvider::class) state: WcSignTransactionUM, +) { + TangemThemePreview { + TangemModalBottomSheet( + config = TangemBottomSheetConfig( + isShown = true, + onDismissRequest = {}, + content = state, + ), + containerColor = TangemTheme.colors.background.tertiary, + title = { + TangemModalBottomSheetTitle( + title = resourceReference(R.string.wc_transaction_request_title), + endIconRes = null, + onEndClick = {}, + startIconRes = R.drawable.ic_back_24, + onStartClick = {}, + ) + }, + content = { + TransactionRequestInfoContent(state = state) + }, + ) + } +} + +private class WcSignTransactionStateProvider : CollectionPreviewParameterProvider( + listOf( + WcSignTransactionUM( + transaction = WcTransactionUM( + appName = "React App", + appIcon = "", + isVerified = true, + appSubtitle = "react-app.walletconnect.com", + walletName = "Tangem 2.0", + networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22), + ), + transactionRequestInfo = WcTransactionRequestInfoUM( + blocks = persistentListOf( + WcTransactionRequestBlockUM( + persistentListOf( + WcTransactionRequestInfoItemUM( + title = resourceReference(R.string.wc_signature_type), + description = "personal_sign", + ), + WcTransactionRequestInfoItemUM( + title = resourceReference(R.string.wc_contents), + description = "Hello! My name is John Dow. test@tange.com", + ), + ), + ), + ), + ), + actions = WcTransactionActionsUM( + onDismiss = {}, + onSign = {}, + onCopy = {}, + ), + ), + WcSignTransactionUM( + transaction = WcTransactionUM( + appName = "React App", + appIcon = "", + isVerified = true, + appSubtitle = "react-app.walletconnect.com", + walletName = "Tangem 2.0", + networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22), + addressText = "0x345FF...34FA", + networkFee = "~ 0.22 $", + ), + transactionRequestInfo = WcTransactionRequestInfoUM( + blocks = persistentListOf( + WcTransactionRequestBlockUM( + persistentListOf( + WcTransactionRequestInfoItemUM( + title = resourceReference(R.string.wc_signature_type), + description = "personal_sign", + ), + WcTransactionRequestInfoItemUM( + title = resourceReference(R.string.wc_contents), + description = "Hello! My name is John Dow. test@tange.com", + ), + ), + ), + WcTransactionRequestBlockUM( + persistentListOf( + WcTransactionRequestInfoItemUM( + title = resourceReference(R.string.wc_transaction_info_to_title), + ), + WcTransactionRequestInfoItemUM( + title = resourceReference(R.string.settings_wallet_name_title), + description = "Bob", + ), + WcTransactionRequestInfoItemUM( + title = resourceReference(R.string.wc_common_wallet), + description = "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + ), + ), + ), + ), + ), + actions = WcTransactionActionsUM( + onDismiss = {}, + onSign = {}, + onCopy = {}, + ), + ), + ), +) \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcAddressItem.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcAddressItem.kt new file mode 100644 index 0000000000..8e9febc9b2 --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcAddressItem.kt @@ -0,0 +1,44 @@ +package com.tangem.features.walletconnect.transaction.ui.common + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.TangemTheme +import com.tangem.features.walletconnect.impl.R + +@Composable +internal fun WcAddressItem(addressText: String, modifier: Modifier = Modifier) { + Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) { + Icon( + modifier = Modifier.size(TangemTheme.dimens.size24), + painter = painterResource(R.drawable.ic_user_square_24), + contentDescription = null, + tint = TangemTheme.colors.icon.accent, + ) + Text( + modifier = Modifier + .padding(start = TangemTheme.dimens.spacing8) + .weight(1f), + text = stringResourceSafe(R.string.wc_common_address), + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.primary1, + ) + Text( + modifier = Modifier + .padding(start = TangemTheme.dimens.spacing16) + .weight(1f), + text = addressText, + textAlign = TextAlign.End, + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.tertiary, + ) + } +} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkFeeItem.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkFeeItem.kt new file mode 100644 index 0000000000..bb4c1867c5 --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkFeeItem.kt @@ -0,0 +1,67 @@ +package com.tangem.features.walletconnect.transaction.ui.common + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.painterResource +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.TangemTheme +import com.tangem.features.walletconnect.impl.R + +@Composable +internal fun WcNetworkFeeItem(networkFeeText: String, modifier: Modifier = Modifier) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + modifier = Modifier.size(TangemTheme.dimens.size24), + painter = painterResource(R.drawable.ic_fee_new_24), + contentDescription = null, + tint = TangemTheme.colors.icon.accent, + ) + + Text( + modifier = Modifier.padding(start = TangemTheme.dimens.spacing8), + text = stringResourceSafe(R.string.common_network_fee_title), + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.primary1, + ) + + Icon( + modifier = Modifier + .padding(start = TangemTheme.dimens.spacing6) + .size(TangemTheme.dimens.size16), + painter = painterResource(id = R.drawable.ic_information_24), + tint = TangemTheme.colors.icon.informative, + contentDescription = null, + ) + + Spacer(modifier = Modifier.weight(1f)) + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.End, + ) { + Text( + text = networkFeeText, + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.tertiary, + ) + Spacer(modifier = Modifier.width(TangemTheme.dimens.spacing6)) + Icon( + modifier = Modifier + .clip(CircleShape) + .size(width = TangemTheme.dimens.size18, height = TangemTheme.dimens.size24), + painter = painterResource(id = R.drawable.ic_select_18_24), + tint = TangemTheme.colors.icon.informative, + contentDescription = null, + ) + } + } +} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkItem.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkItem.kt index 493c205d0e..fe95a18f69 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkItem.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkItem.kt @@ -30,7 +30,7 @@ internal fun WcNetworkItem(networkInfo: WcNetworkInfoUM, modifier: Modifier = Mo ) Text( modifier = Modifier - .padding(start = TangemTheme.dimens.spacing4) + .padding(start = TangemTheme.dimens.spacing8) .weight(1f), text = stringResourceSafe(R.string.wc_common_network), style = TangemTheme.typography.body1, diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcWalletItem.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcWalletItem.kt index 63633a22c1..18babacc67 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcWalletItem.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcWalletItem.kt @@ -25,7 +25,7 @@ internal fun WcWalletItem(walletName: String, modifier: Modifier = Modifier) { ) Text( modifier = Modifier - .padding(start = TangemTheme.dimens.spacing4) + .padding(start = TangemTheme.dimens.spacing8) .weight(1f), text = stringResourceSafe(R.string.manage_tokens_network_selector_wallet), style = TangemTheme.typography.body1, diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheet.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheet.kt deleted file mode 100644 index 004b22bea8..0000000000 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheet.kt +++ /dev/null @@ -1,268 +0,0 @@ -package com.tangem.features.walletconnect.transaction.ui.sign - -import android.content.res.Configuration -import androidx.compose.animation.animateContentSize -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Devices -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider -import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig -import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet -import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.res.TangemTheme -import com.tangem.core.ui.res.TangemThemePreview -import com.tangem.features.walletconnect.impl.R -import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM -import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM -import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestBlockUM -import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoItemUM -import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoUM -import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionUM -import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionUM -import com.tangem.features.walletconnect.transaction.ui.common.WcTransactionRequestInfoContent -import kotlinx.collections.immutable.persistentListOf - -@Composable -internal fun WcSignTransactionModalBottomSheet(config: TangemBottomSheetConfig) { - TangemModalBottomSheet( - config = config, - containerColor = TangemTheme.colors.background.tertiary, - title = { state -> - TangemModalBottomSheetTitle( - title = when (state.state) { - WcSignTransactionUM.State.TRANSACTION -> { - resourceReference(R.string.wallet_connect_title) - } - WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO -> { - resourceReference(R.string.wc_transaction_request_title) - } - }, - endIconRes = R.drawable.ic_close_24.takeIf { - state.state == WcSignTransactionUM.State.TRANSACTION - }, - onEndClick = state.actions.onDismiss, - startIconRes = R.drawable.ic_back_24.takeIf { - state.state == WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO - }, - onStartClick = state.actions.onBack, - ) - }, - content = { state -> - Box( - modifier = Modifier - .fillMaxWidth() - .animateContentSize(), - ) { - when (state.state) { - WcSignTransactionUM.State.TRANSACTION -> { - WcTransactionModalBottomSheetContent(state.transaction, state.actions) - } - WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO -> { - WcTransactionRequestInfoContent(state.transactionRequestInfo, state.actions) - } - } - } - }, - ) -} - -@Composable -@Preview(showBackground = true, device = Devices.PIXEL_7_PRO) -@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES) -private fun WcSignTransactionBottomSheetPreview( - @PreviewParameter(WcSignTransactionStateProvider::class) state: WcSignTransactionUM, -) { - TangemThemePreview { - WcSignTransactionModalBottomSheet( - config = TangemBottomSheetConfig( - isShown = true, - onDismissRequest = {}, - content = state, - ), - ) - } -} - -private class WcSignTransactionStateProvider : CollectionPreviewParameterProvider( - listOf( - WcSignTransactionUM( - state = WcSignTransactionUM.State.TRANSACTION, - transaction = WcTransactionUM( - appName = "React App", - appIcon = "", - isVerified = true, - appSubtitle = "react-app.walletconnect.com", - walletName = "Tangem 2.0", - activeButtonText = resourceReference(R.string.common_sign), - networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22), - ), - transactionRequestInfo = WcTransactionRequestInfoUM( - blocks = persistentListOf( - WcTransactionRequestBlockUM( - persistentListOf( - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_signature_type), - description = "personal_sign", - ), - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_contents), - description = "Hello! My name is John Dow. test@tange.com", - ), - ), - ), - ), - ), - actions = WcTransactionActionsUM( - onDismiss = {}, - onBack = {}, - activeButtonOnClick = {}, - onCopy = {}, - transactionRequestOnClick = {}, - ), - ), - WcSignTransactionUM( - state = WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO, - transaction = WcTransactionUM( - appName = "React App", - appIcon = "", - isVerified = true, - appSubtitle = "react-app.walletconnect.com", - walletName = "Tangem 2.0", - activeButtonText = resourceReference(R.string.common_sign), - networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22), - ), - transactionRequestInfo = WcTransactionRequestInfoUM( - blocks = persistentListOf( - WcTransactionRequestBlockUM( - persistentListOf( - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_signature_type), - description = "personal_sign", - ), - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_contents), - description = "Hello! My name is John Dow. test@tange.com", - ), - ), - ), - ), - ), - actions = WcTransactionActionsUM( - onDismiss = {}, - onBack = {}, - activeButtonOnClick = {}, - onCopy = {}, - transactionRequestOnClick = {}, - ), - ), - WcSignTransactionUM( - state = WcSignTransactionUM.State.TRANSACTION, - transaction = WcTransactionUM( - appName = "React App", - appIcon = "", - isVerified = true, - appSubtitle = "react-app.walletconnect.com", - walletName = "Tangem 2.0", - activeButtonText = resourceReference(R.string.common_sign), - networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22), - addressText = "0x345FF...34FA", - networkFee = "~ 0.22 $", - ), - transactionRequestInfo = WcTransactionRequestInfoUM( - blocks = persistentListOf( - WcTransactionRequestBlockUM( - persistentListOf( - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_signature_type), - description = "personal_sign", - ), - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_contents), - description = "Hello! My name is John Dow. test@tange.com", - ), - ), - ), - WcTransactionRequestBlockUM( - persistentListOf( - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_transaction_info_to_title), - ), - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.settings_wallet_name_title), - description = "Bob", - ), - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_common_wallet), - description = "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", - ), - ), - ), - ), - ), - actions = WcTransactionActionsUM( - onDismiss = {}, - onBack = {}, - activeButtonOnClick = {}, - onCopy = {}, - transactionRequestOnClick = {}, - ), - ), - WcSignTransactionUM( - state = WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO, - transaction = WcTransactionUM( - appName = "React App", - appIcon = "", - isVerified = true, - appSubtitle = "react-app.walletconnect.com", - walletName = "Tangem 2.0", - activeButtonText = resourceReference(R.string.common_sign), - networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22), - addressText = "0x345FF...34FA", - networkFee = "~ 0.22 $", - ), - transactionRequestInfo = WcTransactionRequestInfoUM( - blocks = persistentListOf( - WcTransactionRequestBlockUM( - persistentListOf( - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_signature_type), - description = "personal_sign", - ), - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_contents), - description = "Hello! My name is John Dow. test@tange.com", - ), - ), - ), - WcTransactionRequestBlockUM( - persistentListOf( - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_transaction_info_to_title), - ), - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.settings_wallet_name_title), - description = "Bob", - ), - WcTransactionRequestInfoItemUM( - title = resourceReference(R.string.wc_common_wallet), - description = "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", - ), - ), - ), - ), - ), - actions = WcTransactionActionsUM( - onDismiss = {}, - onBack = {}, - activeButtonOnClick = {}, - onCopy = {}, - transactionRequestOnClick = {}, - ), - ), - ), -) \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheetContent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheetContent.kt new file mode 100644 index 0000000000..398d71924e --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheetContent.kt @@ -0,0 +1,196 @@ +package com.tangem.features.walletconnect.transaction.ui.sign + +import android.content.res.Configuration +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.HorizontalDivider +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.tooling.preview.Devices +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet +import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.walletconnect.connections.ui.WcAppInfoItem +import com.tangem.features.walletconnect.impl.R +import com.tangem.features.walletconnect.transaction.entity.* +import com.tangem.features.walletconnect.transaction.ui.common.* +import kotlinx.collections.immutable.persistentListOf + +@Composable +internal fun WcSignTransactionModalBottomSheetContent( + state: WcSignTransactionUM, + onClickTransactionRequest: () -> Unit, +) { + Column( + modifier = Modifier + .padding(horizontal = TangemTheme.dimens.spacing16), + ) { + Column( + modifier = Modifier + .clip(RoundedCornerShape(TangemTheme.dimens.radius14)) + .background(color = TangemTheme.colors.background.action) + .fillMaxWidth() + .animateContentSize(), + ) { + RequestFromItem() + WcAppInfoItem( + iconUrl = state.transaction.appIcon, + title = state.transaction.appName, + subtitle = state.transaction.appSubtitle, + isVerified = state.transaction.isVerified, + ) + DividerWithPadding(start = 0.dp, end = 0.dp) + WcTransactionRequestItem( + iconRes = R.drawable.ic_doc_new_24, + modifier = Modifier + .fillMaxWidth() + .clickable { onClickTransactionRequest() } + .padding(TangemTheme.dimens.spacing12), + ) + } + Column(modifier = Modifier.padding(top = TangemTheme.dimens.spacing16)) { + WcSignTransactionItems(state) + WcTransactionRequestButtons( + modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing16), + onDismiss = state.actions.onDismiss, + onSign = state.actions.onSign, + isLoading = state.transaction.isLoading, + ) + } + } +} + +@Composable +private fun WcSignTransactionItems(state: WcSignTransactionUM) { + Column( + modifier = Modifier + .clip(RoundedCornerShape(TangemTheme.dimens.radius14)) + .background(color = TangemTheme.colors.background.action) + .fillMaxWidth() + .animateContentSize(), + ) { + val itemsModifier = Modifier + .fillMaxWidth() + .padding(TangemTheme.dimens.spacing12) + + DividerWithPadding(start = 0.dp, end = 0.dp) + WcWalletItem( + modifier = itemsModifier, + walletName = state.transaction.walletName, + ) + DividerWithPadding(start = TangemTheme.dimens.spacing40, end = TangemTheme.dimens.spacing12) + WcNetworkItem( + modifier = itemsModifier, + networkInfo = state.transaction.networkInfo, + ) + if (!state.transaction.addressText.isNullOrEmpty()) { + DividerWithPadding(start = TangemTheme.dimens.spacing40, end = TangemTheme.dimens.spacing12) + WcAddressItem( + modifier = itemsModifier, + addressText = state.transaction.addressText, + ) + } + if (!state.transaction.networkFee.isNullOrEmpty()) { + DividerWithPadding(start = TangemTheme.dimens.spacing40, end = TangemTheme.dimens.spacing12) + WcNetworkFeeItem( + modifier = itemsModifier, + networkFeeText = state.transaction.networkFee, + ) + } + } +} + +@Composable +private fun DividerWithPadding(start: Dp, end: Dp) { + HorizontalDivider( + modifier = Modifier.padding( + start = start, + end = end, + ), + thickness = TangemTheme.dimens.size1, + color = TangemTheme.colors.stroke.primary, + ) +} + +@Composable +@Preview(showBackground = true, device = Devices.PIXEL_7_PRO) +@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES) +private fun WcSignTransactionBottomSheetPreview( + @PreviewParameter(WcSignTransactionStateProvider::class) state: WcSignTransactionUM, +) { + TangemThemePreview { + TangemModalBottomSheet( + config = TangemBottomSheetConfig( + isShown = true, + onDismissRequest = {}, + content = state, + ), + containerColor = TangemTheme.colors.background.tertiary, + title = { + TangemModalBottomSheetTitle( + title = resourceReference(R.string.wallet_connect_title), + endIconRes = R.drawable.ic_close_24, + onEndClick = {}, + startIconRes = null, + onStartClick = {}, + ) + }, + content = { + WcSignTransactionModalBottomSheetContent(state = state, onClickTransactionRequest = {}) + }, + ) + } +} + +private class WcSignTransactionStateProvider : CollectionPreviewParameterProvider( + listOf( + WcSignTransactionUM( + transaction = WcTransactionUM( + appName = "React App", + appIcon = "", + isVerified = true, + appSubtitle = "react-app.walletconnect.com", + walletName = "Tangem 2.0", + networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22), + ), + transactionRequestInfo = WcTransactionRequestInfoUM(persistentListOf()), + actions = WcTransactionActionsUM( + onDismiss = {}, + onSign = {}, + onCopy = {}, + ), + ), + WcSignTransactionUM( + transaction = WcTransactionUM( + appName = "React App", + appIcon = "", + isVerified = true, + appSubtitle = "react-app.walletconnect.com", + walletName = "Tangem 2.0", + networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22), + addressText = "0x345FF...34FA", + networkFee = "~ 0.22 $", + ), + transactionRequestInfo = WcTransactionRequestInfoUM(persistentListOf()), + actions = WcTransactionActionsUM( + onDismiss = {}, + onSign = {}, + onCopy = {}, + ), + ), + ), +) \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/utils/WalletAddressUtils.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/utils/WalletAddressUtils.kt new file mode 100644 index 0000000000..a51a5d82f7 --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/utils/WalletAddressUtils.kt @@ -0,0 +1,7 @@ +package com.tangem.features.walletconnect.transaction.utils + +const val ADDRESS_FIRST_PART_LENGTH = 7 +const val ADDRESS_SECOND_PART_LENGTH = 4 + +internal fun String.toShortAddressText() = + "${take(ADDRESS_FIRST_PART_LENGTH)}...${takeLast(ADDRESS_SECOND_PART_LENGTH)}" \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/utils/WcSignTransactionUtils.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/utils/WcSignTransactionUtils.kt index cb56800329..0442435782 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/utils/WcSignTransactionUtils.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/utils/WcSignTransactionUtils.kt @@ -11,13 +11,13 @@ import com.tangem.domain.walletconnect.usecase.method.WcSignState import com.tangem.domain.walletconnect.usecase.method.WcSignStep import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase import com.tangem.features.walletconnect.impl.R -import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM -import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionUM -import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM -import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestBlockUM -import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoItemUM -import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoUM -import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionUM +import com.tangem.features.walletconnect.transaction.entity.WcNetworkInfoUM +import com.tangem.features.walletconnect.transaction.entity.WcSignTransactionUM +import com.tangem.features.walletconnect.transaction.entity.WcTransactionActionsUM +import com.tangem.features.walletconnect.transaction.entity.WcTransactionRequestBlockUM +import com.tangem.features.walletconnect.transaction.entity.WcTransactionRequestInfoItemUM +import com.tangem.features.walletconnect.transaction.entity.WcTransactionRequestInfoUM +import com.tangem.features.walletconnect.transaction.entity.WcTransactionUM import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @@ -47,7 +47,6 @@ private fun WcMessageSignUseCase.signTypedDataToUM( signModel: WcMessageSignUseCase.SignModel, actions: WcTransactionActionsUM, ) = WcSignTransactionUM( - state = WcSignTransactionUM.State.TRANSACTION, actions = actions, transaction = WcTransactionUM( appName = session.sdkModel.appMetaData.name, @@ -60,7 +59,6 @@ private fun WcMessageSignUseCase.signTypedDataToUM( iconRes = getActiveIconRes(network.id.value), ), addressText = walletAddress.toShortAddressText(), - activeButtonText = resourceReference(R.string.common_sign), isLoading = signState.domainStep == WcSignStep.Signing, ), transactionRequestInfo = WcTransactionRequestInfoUM( @@ -94,7 +92,6 @@ private fun WcMessageSignUseCase.messageSignToUM( signModel: WcMessageSignUseCase.SignModel, actions: WcTransactionActionsUM, ) = WcSignTransactionUM( - state = WcSignTransactionUM.State.TRANSACTION, actions = actions, transaction = WcTransactionUM( appName = session.sdkModel.appMetaData.name, @@ -106,7 +103,6 @@ private fun WcMessageSignUseCase.messageSignToUM( name = network.name, iconRes = getActiveIconRes(network.id.value), ), - activeButtonText = resourceReference(R.string.common_sign), isLoading = signState.domainStep == WcSignStep.Signing, ), transactionRequestInfo = WcTransactionRequestInfoUM( diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 5fbfb3c5e8..9e58bcf67c 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -7,7 +7,7 @@ tangemBlockchainSdk = "develop-1052" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "develop-464" +tangemCardSdk = "develop-468" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem12" #tangemVico = "0.0.1" # Keep it! - used for local builds ^