diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt index a1232dd031..91992dd437 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt @@ -13,7 +13,6 @@ import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWallet import com.tangem.tap.features.saveWallet.redux.SaveWalletReducer import com.tangem.tap.features.send.redux.reducers.SendScreenReducer import com.tangem.tap.features.shop.redux.ShopReducer -import com.tangem.tap.features.signin.redux.SignInReducer import com.tangem.tap.features.tokens.legacy.redux.TokensReducer import com.tangem.tap.features.welcome.redux.WelcomeReducer import com.tangem.tap.proxy.AppStateHolder @@ -40,7 +39,6 @@ fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder) shopState = ShopReducer.reduce(action, state.shopState), welcomeState = WelcomeReducer.reduce(action, state), saveWalletState = SaveWalletReducer.reduce(action, state), - signInState = SignInReducer.reduce(action, state), daggerGraphState = DaggerGraphReducer.reduce(action, state), ) } diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt index 892271058e..72726532fe 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt @@ -31,8 +31,6 @@ import com.tangem.tap.features.send.redux.middlewares.SendMiddleware import com.tangem.tap.features.send.redux.states.SendState import com.tangem.tap.features.shop.redux.ShopMiddleware import com.tangem.tap.features.shop.redux.ShopState -import com.tangem.tap.features.signin.redux.SignInMiddleware -import com.tangem.tap.features.signin.redux.SignInState import com.tangem.tap.features.tokens.legacy.redux.TokensState import com.tangem.tap.features.wallet.redux.middlewares.TradeCryptoMiddleware import com.tangem.tap.features.welcome.redux.WelcomeMiddleware @@ -59,7 +57,6 @@ data class AppState( val shopState: ShopState = ShopState(), val welcomeState: WelcomeState = WelcomeState(), val saveWalletState: SaveWalletState = SaveWalletState(), - val signInState: SignInState = SignInState(), val daggerGraphState: DaggerGraphState = DaggerGraphState(), ) : StateType { @@ -97,7 +94,6 @@ data class AppState( SaveWalletMiddleware().middleware, LockUserWalletsTimerMiddleware().middleware, AccessCodeRequestPolicyMiddleware().middleware, - SignInMiddleware.middleware, DaggerGraphMiddleware.daggerGraphMiddleware, LegacyMiddleware.legacyMiddleware, TradeCryptoMiddleware.middleware, diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectRepository.kt index e38e7fcaf1..de77928810 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectRepository.kt @@ -13,6 +13,7 @@ import com.tangem.tap.features.details.redux.walletconnect.WalletForSession import com.trustwallet.walletconnect.models.WCPeerMeta import com.trustwallet.walletconnect.models.session.WCSession import timber.log.Timber +import java.io.FileNotFoundException import java.nio.charset.Charset class WalletConnectRepository(val context: Application) { @@ -35,6 +36,8 @@ class WalletConnectRepository(val context: Application) { val json = context.readFileText(FILE_NAME_PREFIX_SESSIONS) .hexToUtf8() walletConnectAdapter.fromJson(json)!!.map { it.toSession() } + } catch (e: FileNotFoundException) { + emptyList() } catch (exception: Exception) { Timber.w(exception) emptyList() diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt index 4f37c03839..71f910ce82 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt @@ -14,12 +14,9 @@ import com.walletconnect.android.CoreClient import com.walletconnect.android.relay.ConnectionType import com.walletconnect.web3.wallet.client.Wallet import com.walletconnect.web3.wallet.client.Web3Wallet -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @@ -192,8 +189,8 @@ class WalletConnectRepositoryImpl @Inject constructor( if (sessionDelete is Wallet.Model.SessionDelete.Success) { scope.launch { _events.emit(WalletConnectEvents.SessionDeleted(sessionDelete.topic)) + updateSessionsInternal().join() } - updateSessions() } Timber.d("onSessionDelete: $sessionDelete") } @@ -209,21 +206,21 @@ class WalletConnectRepositoryImpl @Inject constructor( accounts = userNamespaces?.flatMap { it.value } ?: emptyList(), ), ) + updateSessionsInternal().join() } - updateSessions() } } override fun onSessionUpdateResponse(sessionUpdateResponse: Wallet.Model.SessionUpdateResponse) { // Triggered when wallet receives the session update response from Dapp Timber.d("onSessionUpdateResponse: $sessionUpdateResponse") - updateSessions() + updateSessionsInternal() } override fun onConnectionStateChange(state: Wallet.Model.ConnectionState) { // Triggered whenever the connection state is changed Timber.d("onConnectionStateChange: $state") - if (state.isAvailable) updateSessions() + if (state.isAvailable) updateSessionsInternal() } override fun onError(error: Wallet.Model.Error) { @@ -416,7 +413,7 @@ class WalletConnectRepositoryImpl @Inject constructor( dAppUrl = session?.url ?: "", ), ) - updateSessions() + updateSessionsInternal() Timber.d("Disconnected successfully: $it") }, onError = { @@ -440,20 +437,22 @@ class WalletConnectRepositoryImpl @Inject constructor( } override fun updateSessions() { - scope.launch { - val availableSessions = Web3Wallet.getListOfActiveSessions() - .map { - WalletConnectSession( - topic = it.topic, - icon = it.metaData?.icons?.firstOrNull(), - name = it.metaData?.name, - url = it.metaData?.url, - ) - } - Timber.d("Available sessions: $availableSessions") - currentSessions = availableSessions - _activeSessions.emit(availableSessions) - } + updateSessionsInternal() + } + + private fun updateSessionsInternal(): Job = scope.launch { + val availableSessions = Web3Wallet.getListOfActiveSessions() + .map { + WalletConnectSession( + topic = it.topic, + icon = it.metaData?.icons?.firstOrNull(), + name = it.metaData?.name, + url = it.metaData?.url, + ) + } + Timber.d("Available sessions: $availableSessions") + currentSessions = availableSessions + _activeSessions.emit(availableSessions) } private fun findMissingNetworks( 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 c3af721e25..3c71527ab2 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 @@ -37,11 +37,13 @@ class WalletConnectInteractor( suspend fun startListening(userWalletId: String, cardId: String?) { this.userWalletId = userWalletId this.cardId = cardId - walletConnectRepository.updateSessions() + coroutineScope { launch { subscribeToEvents() } launch { subscribeToSessions() } } + + walletConnectRepository.updateSessions() } fun setUserChains(accounts: List) { @@ -88,11 +90,12 @@ class WalletConnectInteractor( is WalletConnectEvents.SessionApprovalSuccess -> { sessionsRepository.saveSession( userWallet = userWalletId, - session = Session.fromAccounts( + session = Session( accounts = wcEvent.accounts, topic = wcEvent.topic, ), ) + walletConnectRepository.updateSessions() handler.onSessionEstablished() } is WalletConnectEvents.SessionDeleted -> { diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/Session.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/Session.kt index 4637a99acb..896b6dc97a 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/Session.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/Session.kt @@ -3,13 +3,4 @@ package com.tangem.tap.domain.walletconnect2.domain.models data class Session( val topic: String, val accounts: List, -) { - companion object { - fun fromAccounts(accounts: List, topic: String): Session { - return Session( - topic = topic, - accounts = accounts, - ) - } - } -} \ No newline at end of file +) \ No newline at end of file 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 8e1bb3f2e1..47afd1b484 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 @@ -59,8 +59,7 @@ sealed class WalletConnectAction : Action { ) : WalletConnectAction() data class FailureEstablishingSession(val session: WCSession?, val error: TapError? = null) : WalletConnectAction() - data class SetSessionsRestored(val sessions: List) : - WalletConnectAction() + data class SetSessionsRestored(val sessions: List) : WalletConnectAction() data class DisconnectSession(val topic: String, val session: WCSession?) : WalletConnectAction() diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt index 44130862c0..6840f26c63 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt @@ -20,8 +20,9 @@ object WalletConnectReducer { is WalletConnectAction.SetNewSessionData -> { state.copy(newSessionData = action.newSession) } - is WalletConnectAction.SetSessionsRestored -> - WalletConnectState(sessions = action.sessions) + is WalletConnectAction.SetSessionsRestored -> state.copy( + sessions = action.sessions, + ) is WalletConnectAction.RemoveSession -> { val sessions = state.sessions.filterNot { it.session.toUri() == action.session.toUri() } diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt index 2bec7b7af6..be5b026c2d 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt @@ -9,8 +9,10 @@ import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.core.analytics.models.Basic import com.tangem.core.navigation.AppScreen import com.tangem.core.navigation.NavigationAction +import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.userwallets.UserWalletBuilder +import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter import com.tangem.tap.common.analytics.events.IntroductionProcess import com.tangem.tap.common.analytics.events.Shop import com.tangem.tap.common.entities.IndeterminateProgressButton @@ -19,7 +21,6 @@ import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.home.redux.HomeMiddleware.NEW_BUY_WALLET_URL import com.tangem.tap.features.send.redux.states.ButtonState -import com.tangem.tap.features.signin.redux.SignInAction import com.tangem.tap.preferencesStorage import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.scope @@ -113,14 +114,32 @@ private fun proceedWithScanResponse(scanResponse: ScanResponse) = scope.launch { Timber.e(error, "Unable to save user wallet") } .doOnSuccess { + sendSignedInCardAnalyticsEvent(scanResponse) scope.launch { store.onUserWalletSelected(userWallet = userWallet) } } .doOnResult { - store.dispatchOnMain(SignInAction.SetSignInType(Basic.SignedIn.SignInType.Card)) navigateTo(AppScreen.Wallet) } } +private fun sendSignedInCardAnalyticsEvent(scanResponse: ScanResponse) { + val currency = ParamCardCurrencyConverter().convert( + value = scanResponse.cardTypesResolver, + ) + + if (currency != null) { + Analytics.send( + event = Basic.SignedIn( + currency = currency, + batch = scanResponse.card.batchId, + signInType = Basic.SignedIn.SignInType.Card, + walletsCount = userWalletsListManager.walletsCount.toString(), + hasBackup = scanResponse.card.backupStatus?.isActive, + ), + ) + } +} + private suspend fun navigateTo(appScreen: AppScreen) { store.dispatchOnMain(NavigationAction.NavigateTo(appScreen)) delay(timeMillis = 200) diff --git a/app/src/main/java/com/tangem/tap/features/signin/redux/SignInAction.kt b/app/src/main/java/com/tangem/tap/features/signin/redux/SignInAction.kt deleted file mode 100644 index 7978ed3f13..0000000000 --- a/app/src/main/java/com/tangem/tap/features/signin/redux/SignInAction.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tangem.tap.features.signin.redux - -import com.tangem.core.analytics.models.Basic -import org.rekotlin.Action - -/** -[REDACTED_AUTHOR] - */ -sealed interface SignInAction : Action { - - data class SetSignInType(val type: Basic.SignedIn.SignInType) : SignInAction -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/signin/redux/SignInMiddleware.kt b/app/src/main/java/com/tangem/tap/features/signin/redux/SignInMiddleware.kt deleted file mode 100644 index 1f44dff0f7..0000000000 --- a/app/src/main/java/com/tangem/tap/features/signin/redux/SignInMiddleware.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.tangem.tap.features.signin.redux - -import com.tangem.tap.common.redux.AppState -import org.rekotlin.Middleware - -/** -[REDACTED_AUTHOR] - */ -object SignInMiddleware { - val middleware: Middleware = { _, _ -> - { next -> - { action -> next(action) } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/signin/redux/SignInReducer.kt b/app/src/main/java/com/tangem/tap/features/signin/redux/SignInReducer.kt deleted file mode 100644 index 3d5910774d..0000000000 --- a/app/src/main/java/com/tangem/tap/features/signin/redux/SignInReducer.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.tangem.tap.features.signin.redux - -import com.tangem.tap.common.redux.AppState -import org.rekotlin.Action - -/** -[REDACTED_AUTHOR] - */ -object SignInReducer { - fun reduce(action: Action, state: AppState): SignInState { - if (action !is SignInAction) return state.signInState - - return when (action) { - is SignInAction.SetSignInType -> state.signInState.copy(type = action.type) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/signin/redux/SignInState.kt b/app/src/main/java/com/tangem/tap/features/signin/redux/SignInState.kt deleted file mode 100644 index 27858a8ad7..0000000000 --- a/app/src/main/java/com/tangem/tap/features/signin/redux/SignInState.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.tangem.tap.features.signin.redux - -import com.tangem.core.analytics.models.Basic - -/** -[REDACTED_AUTHOR] - */ -data class SignInState(val type: Basic.SignedIn.SignInType? = null) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt index ca7d00d461..e2ff46f387 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt @@ -25,7 +25,6 @@ import com.tangem.tap.common.extensions.onUserWalletSelected import com.tangem.tap.common.redux.AppState import com.tangem.tap.features.intentHandler.handlers.BackgroundScanIntentHandler import com.tangem.tap.features.intentHandler.handlers.WalletConnectLinkIntentHandler -import com.tangem.tap.features.signin.redux.SignInAction import com.tangem.tap.proxy.redux.DaggerGraphState import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -98,7 +97,6 @@ internal class WelcomeMiddleware { signInType = Basic.SignedIn.SignInType.Biometric, ) - store.dispatchWithMain(SignInAction.SetSignInType(Basic.SignedIn.SignInType.Biometric)) store.dispatchWithMain(NavigationAction.NavigateTo(AppScreen.Wallet)) store.dispatchWithMain(WelcomeAction.ProceedWithBiometrics.Success) store.onUserWalletSelected(userWallet = selectedUserWallet) @@ -128,7 +126,6 @@ internal class WelcomeMiddleware { .doOnSuccess { sendSignedInAnalyticsEvent(scanResponse = scanResponse, signInType = Basic.SignedIn.SignInType.Card) - store.dispatchWithMain(SignInAction.SetSignInType(Basic.SignedIn.SignInType.Card)) store.dispatchWithMain(NavigationAction.NavigateTo(AppScreen.Wallet)) store.dispatchWithMain(WelcomeAction.ProceedWithCard.Success) store.onUserWalletSelected(userWallet = userWallet) diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index 4566c64fae..1761af22d7 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -410,11 +410,11 @@ internal class StateBuilder( fromToken: CryptoCurrency, warnings: MutableList, ) { - val feeEnoughState = quoteModel.preparedSwapConfigState.feeState - if (feeEnoughState is SwapFeeState.NotEnough && - quoteModel.preparedSwapConfigState.isBalanceEnough && - quoteModel.permissionState !is PermissionDataState.PermissionLoading - ) { + val feeEnoughState = quoteModel.preparedSwapConfigState.feeState as? SwapFeeState.NotEnough ?: return + val needShowCoverWarning = quoteModel.preparedSwapConfigState.isBalanceEnough && + quoteModel.permissionState !is PermissionDataState.PermissionLoading && + feeEnoughState.feeCurrency != fromToken + if (needShowCoverWarning) { warnings.add( SwapWarning.UnableToCoverFeeWarning( createUnableToCoverFeeNotificationConfig( @@ -1027,7 +1027,6 @@ internal class StateBuilder( fun showSelectProviderBottomSheet( uiState: SwapStateHolder, selectedProviderId: String, - bestRatedProviderId: String, pricesLowerBest: Map, providersStates: Map, unavailableProviders: List, @@ -1035,7 +1034,7 @@ internal class StateBuilder( ): SwapStateHolder { val availableProvidersStates = providersStates.entries .mapNotNull { - it.convertToProviderBottomSheetState(pricesLowerBest, bestRatedProviderId, actions.onProviderSelect) + it.convertToProviderBottomSheetState(pricesLowerBest, actions.onProviderSelect) } .sortedWith(ProviderPercentDiffComparator) val unavailableProviderStates = unavailableProviders.map { @@ -1183,7 +1182,6 @@ internal class StateBuilder( private fun Map.Entry.convertToProviderBottomSheetState( pricesLowerBest: Map, - bestRatedProviderId: String, onProviderSelect: (String) -> Unit, ): ProviderState? { val provider = this.key @@ -1191,7 +1189,6 @@ internal class StateBuilder( is SwapState.EmptyAmountState -> null is SwapState.QuotesLoadedState -> { provider.convertToContentSelectableProviderState( - isBestRate = bestRatedProviderId == provider.providerId, state = state, onProviderClick = onProviderSelect, pricesLowerBest = pricesLowerBest, @@ -1301,7 +1298,6 @@ internal class StateBuilder( } private fun SwapProvider.convertToContentSelectableProviderState( - isBestRate: Boolean, state: SwapState.QuotesLoadedState, selectionType: ProviderState.SelectionType, pricesLowerBest: Map, @@ -1311,8 +1307,6 @@ internal class StateBuilder( val rateString = toTokenInfo.tokenAmount.getFormattedCryptoAmount(toTokenInfo.cryptoCurrencyStatus.currency) val additionalBadge = if (state.permissionState is PermissionDataState.PermissionReadyForRequest) { ProviderState.AdditionalBadge.PermissionRequired - } else if (isBestRate) { - ProviderState.AdditionalBadge.BestTrade } else { ProviderState.AdditionalBadge.Empty } diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt index 51969a1ec1..d30242c9f2 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt @@ -928,7 +928,6 @@ internal class SwapViewModel @Inject constructor( selectedProviderId = providerId, pricesLowerBest = pricesLowerBest, unavailableProviders = unavailableProviders, - bestRatedProviderId = findBestQuoteProvider(states)?.providerId ?: providerId, providersStates = dataState.lastLoadedSwapStates, ) { uiState = stateBuilder.dismissBottomSheet(uiState) } },