diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt index 829fdd5601..a13d000c44 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -130,6 +130,11 @@ class DialogManager : StoreSubscriber { preparedData = state.dialog.data, context = context, ) + is WalletConnectDialog.PairConnectErrorDialog -> SimpleAlertDialog.create( + titleRes = R.string.wallet_connect_title, + message = state.dialog.error.message, + context = context, + ) is BackupDialog.AttestationFailed -> AttestationFailedDialog.create(context) is BackupDialog.AddMoreBackupCards -> AddMoreBackupCardsDialog.create(context) is BackupDialog.BackupInProgress -> BackupInProgressDialog.create(context) diff --git a/app/src/main/java/com/tangem/tap/common/redux/legacy/LegacyMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/legacy/LegacyMiddleware.kt index 0b0af1a01b..80d9f694c8 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/legacy/LegacyMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/legacy/LegacyMiddleware.kt @@ -6,6 +6,7 @@ import com.tangem.domain.redux.LegacyAction import com.tangem.domain.tokens.utils.convertToAmount import com.tangem.tap.common.extensions.inject import com.tangem.tap.common.extensions.stripZeroPlainString +import com.tangem.tap.common.feedback.FeedbackEmail import com.tangem.tap.common.feedback.RateCanBeBetterEmail import com.tangem.tap.common.feedback.SendTransactionFailedEmail import com.tangem.tap.common.redux.AppState @@ -27,6 +28,12 @@ internal object LegacyMiddleware { scanResponse = action.scanResponse, ) } + is LegacyAction.SendEmailSupport -> { + store.state.globalState.feedbackManager?.sendEmail( + feedbackData = FeedbackEmail(), + scanResponse = action.scanResponse, + ) + } is LegacyAction.StartOnboardingProcess -> { store.dispatch( GlobalAction.Onboarding.Start(action.scanResponse, canSkipBackup = action.canSkipBackup), diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/GeneralUserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/GeneralUserWalletsListManager.kt index 4565c111ed..2901b7120b 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/GeneralUserWalletsListManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/GeneralUserWalletsListManager.kt @@ -48,21 +48,33 @@ internal class GeneralUserWalletsListManager( get() = requireImplementation.isLockable override val userWallets: Flow> - get() = implementation.transformLatest { impl -> - if (impl != null && impl.hasUserWallets) { - emitAll(impl.userWallets) + get() = implementation + .transformLatest { impl -> + if (impl != null) { + emitAll(impl.userWallets) + } } - } + // To avoid returning empty flow to subscriber while implementation and userWallets are null + // Flow is called first time when implementation is null and then when its assigned with implementation + // that may have not user wallets (null or empty). + // As a result subscription occurs on empty flow, than will not change if user wallets are available + .filter { requireImplementation.hasUserWallets } override val userWalletsSync: List get() = requireImplementation.userWalletsSync override val selectedUserWallet: Flow - get() = implementation.transformLatest { impl -> - if (impl != null && impl.hasUserWallets) { - emitAll(impl.selectedUserWallet) + get() = implementation + .transformLatest { impl -> + if (impl != null) { + emitAll(impl.selectedUserWallet) + } } - } + // To avoid returning empty flow to subscriber while implementation and userWallets are null + // Flow is called first time when implementation is null and then when its assigned with implementation + // that may have not user wallets (null or empty). + // As a result subscription occurs on empty flow, than will not change if user wallets are available + .filter { requireImplementation.hasUserWallets } override val selectedUserWalletSync: UserWallet? get() = requireImplementation.selectedUserWalletSync diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/app/WalletConnectEventsHandlerImpl.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/app/WalletConnectEventsHandlerImpl.kt index 909f4dafb7..073fcb8f0d 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/app/WalletConnectEventsHandlerImpl.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/app/WalletConnectEventsHandlerImpl.kt @@ -46,4 +46,8 @@ internal class WalletConnectEventsHandlerImpl : WalletConnectEventsHandler { override fun onUnsupportedRequest() { store.dispatchOnMain(WalletConnectAction.RejectUnsupportedRequest) } + + override fun onPairConnectError(error: Throwable) { + store.dispatchOnMain(WalletConnectAction.PairConnectErrorAction(error)) + } } \ No newline at end of file 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 04a4940928..4266b2fa73 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 @@ -246,7 +246,20 @@ internal class DefaultLegacyWalletConnectRepository( } override fun pair(uri: String) { - Web3Wallet.pair(Wallet.Params.Pair(uri)) + Web3Wallet.pair( + params = Wallet.Params.Pair(uri), + onSuccess = { + Timber.i("Paired successfully: $it") + }, + onError = { + Timber.e("Error while pairing: $it") + scope.launch { + _events.emit( + WalletConnectEvents.PairConnectError(it.throwable), + ) + } + }, + ) } override fun approve(userNamespaces: Map>) { diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/di/WalletConnectInteractorModule.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/di/WalletConnectInteractorModule.kt index d4fef91bab..cc4a3e16c4 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/di/WalletConnectInteractorModule.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/di/WalletConnectInteractorModule.kt @@ -14,26 +14,24 @@ import com.tangem.tap.domain.walletconnect2.app.TangemWcBlockchainHelper import com.tangem.tap.domain.walletconnect2.app.WalletConnectEventsHandlerImpl import com.tangem.tap.domain.walletconnect2.data.DefaultLegacyWalletConnectRepository import com.tangem.tap.domain.walletconnect2.data.DefaultWalletConnectSessionsRepository -import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository +import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository import com.tangem.tap.domain.walletconnect2.domain.WcJrpcRequestsDeserializer import com.tangem.tap.domain.walletconnect2.toggles.WalletConnectFeatureToggles -import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.components.ActivityComponent -import dagger.hilt.android.scopes.ActivityScoped import dagger.hilt.components.SingletonComponent import javax.inject.Singleton @Module -@InstallIn(ActivityComponent::class) +@InstallIn(SingletonComponent::class) internal object WalletConnectInteractorModule { @Provides - @ActivityScoped + @Singleton fun provideWalletConnectInteractor( wcRepository: LegacyWalletConnectRepository, wcSessionsRepository: WalletConnectSessionsRepository, @@ -41,6 +39,7 @@ internal object WalletConnectInteractorModule { currenciesRepository: CurrenciesRepository, walletManagersFacade: WalletManagersFacade, userWalletsListManager: UserWalletsListManager, + coroutineDispatcherProvider: CoroutineDispatcherProvider, ): WalletConnectInteractor { return WalletConnectInteractor( handler = WalletConnectEventsHandlerImpl(), @@ -51,7 +50,7 @@ internal object WalletConnectInteractorModule { currenciesRepository = currenciesRepository, walletManagersFacade = walletManagersFacade, userWalletsListManager = userWalletsListManager, - dispatchers = AppCoroutineDispatcherProvider(), + dispatchers = coroutineDispatcherProvider, ) } } diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectEventsHandler.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectEventsHandler.kt index 30c73a0642..b9414d247e 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectEventsHandler.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectEventsHandler.kt @@ -16,4 +16,6 @@ interface WalletConnectEventsHandler { fun onSessionRequest(request: WcPreparedRequest) fun onUnsupportedRequest() + + fun onPairConnectError(error: Throwable) } \ No newline at end of file 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 b63a1d0005..66f8b5d16c 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 @@ -9,18 +9,18 @@ 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.usecase.GetSelectedWalletUseCase +import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.filterNotNull import com.tangem.tap.domain.walletconnect.WalletConnectSdkHelper import com.tangem.tap.domain.walletconnect2.domain.models.* +import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.details.ui.walletconnect.WcSessionForScreen +import com.tangem.tap.store import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import com.tangem.utils.coroutines.FeatureCoroutineExceptionHandler -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.cancelChildren +import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch import timber.log.Timber +import java.util.Stack @Suppress("LargeClass", "LongParameterList") class WalletConnectInteractor( @@ -35,18 +35,27 @@ class WalletConnectInteractor( val blockchainHelper: WcBlockchainHelper, ) { + var isWalletConnectReadyForDeepLinks = false + private val getSelectedWalletUseCase by lazy(LazyThreadSafetyMode.NONE) { GetSelectedWalletUseCase(userWalletsListManager) } private val wcScope = CoroutineScope( - Job() + dispatchers.io + FeatureCoroutineExceptionHandler.create("wcScope"), + SupervisorJob() + dispatchers.io + CoroutineExceptionHandler { _, throwable -> + Timber.e("CoroutineException: from: LISTENER SCOPE, exception: $throwable") + }, ) private val listenerScope = CoroutineScope( - Job() + dispatchers.io + FeatureCoroutineExceptionHandler.create("listenScope"), + SupervisorJob() + dispatchers.io + CoroutineExceptionHandler { _, throwable -> + Timber.e("CoroutineException: from: LISTENER SCOPE, exception: $throwable") + }, ) + /** Stack of deeplinks to handle if user wallet is not selected or cryptocurrency statuses are not available */ + private val deeplinkStack: Stack = Stack() + private val events = walletConnectRepository.events private val sessions = walletConnectRepository.activeSessions @@ -96,6 +105,7 @@ class WalletConnectInteractor( networks = currencies.map { it.network }, ) setUserChains(accounts) + handleDeeplinkStack(accounts) } private suspend fun startListeningWc(userWalletId: String, cardId: String?) { @@ -118,6 +128,17 @@ class WalletConnectInteractor( walletConnectRepository.setUserNamespaces(userNamespaces) } + private fun handleDeeplinkStack(accounts: List) { + runCatching { + if (accounts.isEmpty()) return + isWalletConnectReadyForDeepLinks = true + val lastDeeplink = deeplinkStack.pop() + store.dispatchOnMain(WalletConnectAction.OpenSession(lastDeeplink)) + }.onFailure { + Timber.e("WC deeplink handling failed. $it") + } + } + private suspend fun subscribeToEvents() { events .onEach { wcEvent -> @@ -167,6 +188,9 @@ class WalletConnectInteractor( is WalletConnectEvents.SessionRequest -> { handleRequest(wcEvent) } + is WalletConnectEvents.PairConnectError -> { + handler.onPairConnectError(wcEvent.error) + } } } .flowOn(dispatchers.io) @@ -329,6 +353,21 @@ class WalletConnectInteractor( return uri.lowercase().startsWith(WC_SCHEME) } + /** + * Handles Wallet Connect deep links. + * If wallet connect is able to handle the deeplink, session is started with deeplink. + * Otherwise, deeplink is stored until wallet connect is ready to handle it. + * + * @param deeplink deeplink to handle + */ + fun addDeeplink(deeplink: String) { + if (isWalletConnectReadyForDeepLinks) { + store.dispatchOnMain(WalletConnectAction.OpenSession(deeplink)) + } else { + deeplinkStack.push(deeplink) + } + } + private fun getCardId(userWallet: UserWallet): String? { return if (userWallet.scanResponse.card.backupStatus?.isActive != true) { userWallet.cardId diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/WalletConnectEvents.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/WalletConnectEvents.kt index d47c296a42..85e6e06f5b 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/WalletConnectEvents.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/WalletConnectEvents.kt @@ -26,4 +26,6 @@ sealed interface WalletConnectEvents { val metaUrl: String, val method: String, ) : WalletConnectEvents + + data class PairConnectError(val error: Throwable) : WalletConnectEvents } \ 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 e96974c3b4..a6c5dabb19 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 @@ -22,17 +22,19 @@ sealed class WalletConnectAction : Action { data class ShowClipboardOrScanQrDialog(val wcUri: String) : WalletConnectAction() //region WalletConnect 2.0 - object ApproveProposal : WalletConnectAction() - object RejectProposal : WalletConnectAction() + data object ApproveProposal : WalletConnectAction() + data object RejectProposal : WalletConnectAction() - object SessionEstablished : WalletConnectAction() + data object SessionEstablished : WalletConnectAction() data class SessionRejected(val error: WalletConnectError) : WalletConnectAction() data class SessionListUpdated(val sessions: List) : WalletConnectAction() data class ShowSessionRequest(val sessionRequest: WcPreparedRequest) : WalletConnectAction() - object RejectUnsupportedRequest : WalletConnectAction() + data object RejectUnsupportedRequest : WalletConnectAction() data class PerformRequestedAction(val sessionRequest: WcPreparedRequest) : WalletConnectAction() + + data class PairConnectErrorAction(val throwable: Throwable) : WalletConnectAction() //endregion WalletConnect 2.0 } \ No newline at end of file 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 f55288968a..6b0e0898ec 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 @@ -47,8 +47,11 @@ class WalletConnectMiddleware { when (action) { is WalletConnectAction.HandleDeepLink -> { - if (!action.wcUri.isNullOrBlank()) { - store.dispatchOnMain(WalletConnectAction.OpenSession(action.wcUri)) + val wsUrl = action.wcUri + Timber.i("WC deeplink: $wsUrl") + if (!wsUrl.isNullOrBlank()) { + Timber.i("WC deeplink added to stack: $wsUrl") + walletConnectInteractor.addDeeplink(wsUrl) } } is WalletConnectAction.DisconnectSession -> { @@ -172,6 +175,9 @@ class WalletConnectMiddleware { is WalletConnectAction.RejectUnsupportedRequest -> { store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedNetwork())) } + is WalletConnectAction.PairConnectErrorAction -> { + store.dispatch(GlobalAction.ShowDialog(WalletConnectDialog.PairConnectErrorDialog(action.throwable))) + } } } 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 20217386f2..a7640ed758 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 @@ -14,6 +14,7 @@ object WalletConnectReducer { is WalletConnectAction.RejectProposal, is WalletConnectAction.SessionEstablished, is WalletConnectAction.SessionRejected, + is WalletConnectAction.PairConnectErrorAction, -> state.copy(loading = false) is WalletConnectAction.SessionListUpdated -> state.copy( wc2Sessions = action.sessions, diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt index 65d11fc520..d1a9368288 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt @@ -117,6 +117,8 @@ sealed class WalletConnectDialog : StateDialog { data class SignTransactionDialog( val data: WcPreparedRequest.SignTransaction, ) : WalletConnectDialog() + + data class PairConnectErrorDialog(val error: Throwable) : WalletConnectDialog() } data class WcTransactionData( diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index efa987c847..c86ed79d1d 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -480,7 +480,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) when (result) { is CompletionResult.Success -> { val backupValidator = BackupValidator() - if (!backupValidator.isValid(CardDTO(result.data))) { + if (!backupValidator.isValidBackupStatus(CardDTO(result.data))) { store.dispatchOnMain(BackupAction.ErrorInBackupCard) } if (backupService.currentState == BackupService.State.Finished) { diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index aa18939439..e67145ee33 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -424,7 +424,7 @@ Код доступа Группы По балансу - Сортировка токенов + Упорядочить токены Список Выбрать из галереи Настройки @@ -710,7 +710,7 @@ Настройки кошелька Tangem Используйте %s или отсканируйте карту, чтобы разблокировать доступ к вашему кошельку - Пожалуйста, выведите все средства из этого кошелька, сбросьте его к заводским настройкам и создайте новый. Доступ к текущему кошельку будет утерян. + Похоже, что процесс активации карт не был завершен корректно. Это могло быть вызвано проблемой взаимодействия с модулем NFC либо некорректным прикладыванием карты к телефону. Пожалуйста, обратитесь в нашу службу поддержки для уточнения деталей. Ошибка активации По решению разработчиков сети BNB стандарт BEP-2 перестанет поддерживаться в июне 2024 года. Чтобы не потерять активы, их необходимо преобразовать в стандарт BEP-20. Используйте функцию обмена в приложении или сторонние сервисы, чтобы перевести средства в cеть BNB Smart Chain. Отключение сети BNB Beacon Chain diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 954e7e59ca..276eb46615 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -795,7 +795,7 @@ Wallet settings Tangem Use %s or scan a card to unlock access to your wallet - Please withdraw all funds from this wallet, reset it to factory settings, and create a new one. Access to the current wallet will be lost. + It seems that the card activation was not completed correctly. This could be due to an issue with your device\'s NFC module or incorrect tapping of the card to your device. Please contact our Support team for assistance. Activation error According to BNB network developers, support for the BEP-2 standard will end in June 2024. To avoid losing assets with this standard, please convert them to the BEP-20 standard. Use our swap service or third-party services to transfer funds to the BNB Smart Chain network. BNB Beacon Chain will shut down diff --git a/domain/legacy/src/main/java/com/tangem/domain/redux/LegacyAction.kt b/domain/legacy/src/main/java/com/tangem/domain/redux/LegacyAction.kt index 68c6988923..ab0183d09e 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/redux/LegacyAction.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/redux/LegacyAction.kt @@ -8,6 +8,8 @@ import java.math.BigDecimal sealed interface LegacyAction : Action { + data class SendEmailSupport(val scanResponse: ScanResponse) : LegacyAction + data class SendEmailRateCanBeBetter(val scanResponse: ScanResponse) : LegacyAction /** diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/BackupValidator.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/BackupValidator.kt index 4153d69e68..d83e759503 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/BackupValidator.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/BackupValidator.kt @@ -7,10 +7,14 @@ import javax.inject.Inject class BackupValidator @Inject constructor() { - fun isValid(cardDTO: CardDTO): Boolean { + fun isValidFull(cardDTO: CardDTO): Boolean { return validateBackupStatus(cardDTO) && validateCurves(cardDTO) } + fun isValidBackupStatus(cardDTO: CardDTO): Boolean { + return validateBackupStatus(cardDTO) + } + private fun validateCurves(cardDTO: CardDTO): Boolean { val config = CardConfig.createConfig(cardDTO) // / Since the curve `bls12381_G2_AUG` was added later into first generation of wallets, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt index 25ef6de005..031c843c16 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt @@ -53,7 +53,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( buildList { addSwapPromoNotification(shouldShowPromo, promoBanner, clickIntents) - addCriticalNotifications(userWallet) + addCriticalNotifications(userWallet, clickIntents) addInformationalNotifications(cardTypesResolver, maybeTokenList, clickIntents) @@ -87,11 +87,14 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( ) } - private fun MutableList.addCriticalNotifications(userWallet: UserWallet) { + private fun MutableList.addCriticalNotifications( + userWallet: UserWallet, + clickIntents: WalletClickIntents, + ) { val cardTypesResolver = userWallet.scanResponse.cardTypesResolver addIf( - element = WalletNotification.Critical.BackupError, - condition = !backupValidator.isValid(userWallet.scanResponse.card) || userWallet.hasBackupError, + element = WalletNotification.Critical.BackupError { clickIntents.onSupportClick() }, + condition = !backupValidator.isValidBackupStatus(userWallet.scanResponse.card) || userWallet.hasBackupError, ) addIf( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt index 0ed8bda419..c878757dbc 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt @@ -19,11 +19,16 @@ import org.joda.time.DateTime @Immutable sealed class WalletNotification(val config: NotificationConfig) { - sealed class Critical(title: TextReference, subtitle: TextReference) : WalletNotification( + sealed class Critical( + title: TextReference, + subtitle: TextReference, + buttonsState: NotificationConfig.ButtonsState? = null, + ) : WalletNotification( config = NotificationConfig( title = title, subtitle = subtitle, iconResId = R.drawable.ic_alert_circle_24, + buttonsState = buttonsState, ), ) { @@ -37,9 +42,13 @@ sealed class WalletNotification(val config: NotificationConfig) { subtitle = resourceReference(id = R.string.warning_failed_to_verify_card_message), ) - data object BackupError : Critical( + data class BackupError(val onSupportClick: () -> Unit) : Critical( title = resourceReference(R.string.warning_backup_errors_title), subtitle = resourceReference(R.string.warning_backup_errors_message), + buttonsState = NotificationConfig.ButtonsState.PrimaryButtonConfig( + text = resourceReference(id = R.string.details_row_title_contact_to_support), + onClick = onSupportClick, + ), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt index e90a55faac..b8ee6c5ef5 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt @@ -62,6 +62,8 @@ internal interface WalletWarningsClickIntents { fun onTravalaPromoClick(link: String?) fun onCloseTravalaPromoClick() + + fun onSupportClick() } @Suppress("LongParameterList") @@ -262,6 +264,15 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( } } + override fun onSupportClick() { + reduxStateHolder.dispatch( + LegacyAction.SendEmailSupport( + scanResponse = getSelectedUserWallet()?.scanResponse + ?: error("ScanResponse must be not null"), + ), + ) + } + private fun getSelectedUserWallet(): UserWallet? { val userWalletId = stateHolder.getSelectedWalletId() return getUserWalletUseCase(userWalletId).getOrElse { diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index ce194116f9..d6bb419a92 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -88,7 +88,7 @@ markdown = "0.7.2" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "develop-702" +tangemBlockchainSdk = "develop-703" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-375" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^