From 35253cded59e886366e04d7ec4e7dad64a55799d Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 13 Oct 2025 12:22:50 +0200 Subject: [PATCH 1/8] Updated on 2026-08-14 --- .../tap/di/domain/WalletsDomainModule.kt | 16 ++++ .../DefaultNotificationsRepository.kt | 6 +- ...letsForAutomaticallyPushEnablingUseCase.kt | 15 +++- .../model/PushNotificationsClickIntents.kt | 2 +- .../impl/model/PushNotificationsModel.kt | 13 ++-- .../ui/PushNotificationsBottomSheet.kt | 6 +- .../ui/PushNotificationsScreen.kt | 6 +- .../wallet/child/wallet/model/WalletModel.kt | 11 +-- .../intents/WalletWarningsClickIntents.kt | 73 ++++++++++--------- 9 files changed, 79 insertions(+), 69 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt index 0f7e759701..f997c6b4e0 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt @@ -471,4 +471,20 @@ internal object WalletsDomainModule { yieldSupplyMarketRepository = yieldSupplyMarketRepository, ) } + + @Provides + @Singleton + fun provideGetWalletsForAutomaticallyPushEnablingUseCase( + userWalletsListManager: UserWalletsListManager, + userWalletsListRepository: UserWalletsListRepository, + hotWalletFeatureToggles: HotWalletFeatureToggles, + dispatcherProvider: CoroutineDispatcherProvider, + ): GetWalletsForAutomaticallyPushEnablingUseCase { + return GetWalletsForAutomaticallyPushEnablingUseCase( + userWalletsListManager = userWalletsListManager, + userWalletsListRepository = userWalletsListRepository, + shouldUseNewListRepository = hotWalletFeatureToggles.isHotWalletEnabled, + dispatchers = dispatcherProvider, + ) + } } \ No newline at end of file diff --git a/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt b/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt index 28d912b189..5795eed9b7 100644 --- a/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt +++ b/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt @@ -2,11 +2,7 @@ package com.tangem.data.notifications import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys -import com.tangem.datasource.local.preferences.utils.get -import com.tangem.datasource.local.preferences.utils.getObjectMapSync -import com.tangem.datasource.local.preferences.utils.getSyncOrDefault -import com.tangem.datasource.local.preferences.utils.getSyncOrNull -import com.tangem.datasource.local.preferences.utils.store +import com.tangem.datasource.local.preferences.utils.* import com.tangem.domain.notifications.repository.NotificationsRepository import kotlinx.coroutines.flow.Flow import javax.inject.Inject diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetWalletsForAutomaticallyPushEnablingUseCase.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetWalletsForAutomaticallyPushEnablingUseCase.kt index 3eb6bc9629..75c623d401 100644 --- a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetWalletsForAutomaticallyPushEnablingUseCase.kt +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetWalletsForAutomaticallyPushEnablingUseCase.kt @@ -1,27 +1,34 @@ package com.tangem.domain.wallets.usecase +import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.withContext -import javax.inject.Inject /** * Use case for retrieving wallets where automatically enabling push notifications was not applied. * * This use case filters out wallets that have already had push notifications automatically enabled * from the complete list of user wallets, returning only those wallets that still need to have * push notifications automatically enabled. - * * @property userWalletsListManager Manager for user wallets list operations + * @property userWalletsListManager Manager for user wallets list operations + * @property userWalletsListRepository Repository for user wallets list operations * @property dispatchers Coroutine dispatcher provider for background operations */ -class GetWalletsForAutomaticallyPushEnablingUseCase @Inject constructor( +class GetWalletsForAutomaticallyPushEnablingUseCase( private val userWalletsListManager: UserWalletsListManager, + private val userWalletsListRepository: UserWalletsListRepository, + private val shouldUseNewListRepository: Boolean, private val dispatchers: CoroutineDispatcherProvider, ) { suspend operator fun invoke(walletsListWherePushWasEnabled: List): List = withContext(dispatchers.default) { - val allLocalWallets = userWalletsListManager.userWalletsSync.map { it.walletId } + val allLocalWallets = if (shouldUseNewListRepository) { + userWalletsListRepository.userWalletsSync().map { it.walletId } + } else { + userWalletsListManager.userWalletsSync.map { it.walletId } + } allLocalWallets - walletsListWherePushWasEnabled.toSet() } } \ No newline at end of file diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsClickIntents.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsClickIntents.kt index 17ad5e9b9c..ad7b69bc71 100644 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsClickIntents.kt +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsClickIntents.kt @@ -3,7 +3,7 @@ package com.tangem.features.pushnotifications.impl.model internal interface PushNotificationsClickIntents { fun onAllowClick() - fun onLaterClick(isFromBs: Boolean) + fun onLaterClick() fun onAllowPermission() diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsModel.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsModel.kt index 4f796a7ad2..edc28adbb1 100644 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsModel.kt +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsModel.kt @@ -49,18 +49,15 @@ internal class PushNotificationsModel @Inject constructor( analyticHandler.send(PushNotificationAnalyticEvents.ButtonAllow(source)) } - override fun onLaterClick(isFromBs: Boolean) { - modelScope.launch { - notificationsRepository.setUserAllowToSubscribeOnPushNotifications(false) - } + override fun onLaterClick() { analyticHandler.send(PushNotificationAnalyticEvents.ButtonLater(source)) modelScope.launch { - if (isFromBs) { - neverRequestPermissionUseCase(PUSH_PERMISSION) - } + neverRequestPermissionUseCase(PUSH_PERMISSION) neverToInitiallyAskPermissionUseCase(PUSH_PERMISSION) params.modelCallbacks.onDenySystemPermission() - if (!params.isBottomSheet) { + if (params.isBottomSheet) { + notificationsRepository.setUserAllowToSubscribeOnPushNotifications(false) + } else { params.nextRoute?.let { appRouter.push(it) } } } diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsBottomSheet.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsBottomSheet.kt index c240a0bc72..ce560cf41e 100644 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsBottomSheet.kt +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsBottomSheet.kt @@ -41,7 +41,7 @@ internal fun PushNotificationsBottomSheet(config: TangemBottomSheetConfig, conte @Composable internal fun PushNotificationsContent( onAllowClick: () -> Unit, - onLaterClick: (isFromBs: Boolean) -> Unit, + onLaterClick: () -> Unit, onAllowPermission: () -> Unit, onDenyPermission: () -> Unit, ) { @@ -77,9 +77,7 @@ internal fun PushNotificationsContent( requestPushPermission() }, secondaryButtonText = resourceReference(R.string.common_later), - onSecondaryClick = { - onLaterClick(true) - }, + onSecondaryClick = onLaterClick, ) } } diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt index 9129169337..9cda2da392 100644 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt @@ -15,7 +15,7 @@ import kotlinx.collections.immutable.persistentListOf @Composable internal fun PushNotificationsScreen( onAllowClick: () -> Unit, - onLaterClick: (isFromBs: Boolean) -> Unit, + onLaterClick: () -> Unit, onAllowPermission: () -> Unit, onDenyPermission: () -> Unit, ) { @@ -49,9 +49,7 @@ internal fun PushNotificationsScreen( ), secondaryButton = ShowcaseButtonModel( buttonText = resourceReference(R.string.common_later), - onClick = { - onLaterClick(false) - }, + onClick = onLaterClick, ), modifier = Modifier.systemBarsPadding(), ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt index c843cb1153..639d9da483 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt @@ -41,7 +41,6 @@ import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvid import com.tangem.features.biometry.AskBiometryComponent import com.tangem.features.hotwallet.HotWalletFeatureToggles import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks -import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION import com.tangem.features.tangempay.TangemPayFeatureToggles import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles @@ -76,7 +75,6 @@ internal class WalletModel @Inject constructor( private val selectedWalletAnalyticsSender: SelectedWalletAnalyticsSender, private val walletNameMigrationUseCase: WalletNameMigrationUseCase, private val refreshMultiCurrencyWalletQuotesUseCase: RefreshMultiCurrencyWalletQuotesUseCase, - private val shouldAskPermissionUseCase: ShouldAskPermissionUseCase, private val walletImageResolver: WalletImageResolver, private val tokenListStore: MultiWalletTokenListStore, private val onrampStatusFactory: OnrampStatusFactory, @@ -238,19 +236,16 @@ internal class WalletModel @Inject constructor( private fun subscribeOnPushNotificationsPermission() { modelScope.launch { - val shouldAskPermission = shouldAskPermissionUseCase(PUSH_PERMISSION) - val afterUpdate = notificationsRepository.shouldShowSubscribeOnNotificationsAfterUpdate() + val shouldShow = notificationsRepository.shouldShowSubscribeOnNotificationsAfterUpdate() val isBiometricsEnabled = shouldSaveUserWalletsSyncUseCase() val isHuaweiDevice = getIsHuaweiDeviceWithoutGoogleServicesUseCase() - val shouldShowBottomSheet = shouldAskPermission || afterUpdate Timber.d( - "push BS afterUpdate: $afterUpdate," + - "shouldAskPermission $shouldAskPermission," + + "push BS afterUpdate: $shouldShow," + "isBiometricsEnabled $isBiometricsEnabled," + "isHuaweiDevice $isHuaweiDevice", ) if (!isBiometricsEnabled) return@launch - if (!shouldShowBottomSheet) return@launch + if (!shouldShow) return@launch delay(timeMillis = 1_800) 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 d1e7c8cba5..25b487ec43 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 @@ -1,6 +1,5 @@ package com.tangem.feature.wallet.child.wallet.model.intents -import android.os.Build import arrow.core.getOrElse import com.tangem.common.TangemBlogUrlBuilder import com.tangem.common.routing.AppRoute.* @@ -32,16 +31,12 @@ import com.tangem.domain.promo.models.PromoId import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher import com.tangem.domain.settings.NeverToSuggestRateAppUseCase import com.tangem.domain.settings.RemindToRateAppLaterUseCase -import com.tangem.domain.settings.repositories.PermissionRepository import com.tangem.domain.staking.StakingIdFactory import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType import com.tangem.domain.wallets.models.UnlockWalletsError -import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase -import com.tangem.domain.wallets.usecase.GetUserWalletUseCase -import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase -import com.tangem.domain.wallets.usecase.UnlockWalletsUseCase +import com.tangem.domain.wallets.usecase.* import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent @@ -139,8 +134,9 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( private val userWalletsListRepository: UserWalletsListRepository, private val setShouldShowNotificationUseCase: SetShouldShowNotificationUseCase, private val notificationsRepository: NotificationsRepository, - private val permissionRepository: PermissionRepository, private val messageSender: UiMessageSender, + private val setNotificationsEnabledUseCase: SetNotificationsEnabledUseCase, + private val getWalletsListForEnablingUseCase: GetWalletsForAutomaticallyPushEnablingUseCase, ) : BaseWalletClickIntents(), WalletWarningsClickIntents { private val finalizeWalletSetupAlertBS @@ -477,49 +473,42 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( override fun onAllowPermissions() { analyticsEventHandler.send(WalletScreenAnalyticsEvent.PushBannerPromo.ButtonAllowPush) - if (isNotificationsPermissionGranted()) { - updateSubscribeOnPushPermissions(true) - } else { - walletEventSender.send( - event = WalletEvent.RequestPushPermissions( - onAllow = { + walletEventSender.send( + event = WalletEvent.RequestPushPermissions( + onAllow = { + modelScope.launch { updateSubscribeOnPushPermissions(true) analyticsEventHandler.send( PushNotificationAnalyticEvents.PermissionStatus(isAllowed = true), ) - }, - onDeny = { + enableNotificationsIfNeeded() + } + }, + onDeny = { + modelScope.launch { updateSubscribeOnPushPermissions(false) analyticsEventHandler.send( PushNotificationAnalyticEvents.PermissionStatus(isAllowed = false), ) - }, - ), - ) - } + } + }, + ), + ) } override fun onDenyPermissions() { - analyticsEventHandler.send(WalletScreenAnalyticsEvent.PushBannerPromo.ButtonLaterPush) - updateSubscribeOnPushPermissions(false) - } - - private fun updateSubscribeOnPushPermissions(shouldAllow: Boolean) { modelScope.launch { - notificationsRepository.setUserAllowToSubscribeOnPushNotifications(shouldAllow) - setShouldShowNotificationUseCase( - key = NotificationId.EnablePushesReminderNotification.key, - value = false, - ) + analyticsEventHandler.send(WalletScreenAnalyticsEvent.PushBannerPromo.ButtonLaterPush) + updateSubscribeOnPushPermissions(false) } } - private fun isNotificationsPermissionGranted(): Boolean { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - permissionRepository.hasRuntimePermission(android.Manifest.permission.POST_NOTIFICATIONS) - } else { - true - } + private suspend fun updateSubscribeOnPushPermissions(shouldAllow: Boolean) { + notificationsRepository.setUserAllowToSubscribeOnPushNotifications(shouldAllow) + setShouldShowNotificationUseCase( + key = NotificationId.EnablePushesReminderNotification.key, + value = false, + ) } private suspend fun fetchCryptoCurrencies(userWalletId: UserWalletId, currencies: List) { @@ -572,4 +561,18 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( null } } + + private suspend fun enableNotificationsIfNeeded() { + val alreadyEnabledWallets = notificationsRepository.getWalletAutomaticallyEnabledList().map { + UserWalletId(it) + } + val walletsListWhichShouldBeEnabled = getWalletsListForEnablingUseCase(alreadyEnabledWallets) + walletsListWhichShouldBeEnabled.forEach { userWalletId -> + setNotificationsEnabledUseCase(userWalletId, true).onRight { + notificationsRepository.setNotificationsWasEnabledAutomatically(userWalletId.stringValue) + }.onLeft { + Timber.e(it) + } + } + } } \ No newline at end of file From 9ad4259a5c21e3d75c16ac99ebf15081e970db5c Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 13 Oct 2025 13:06:39 +0200 Subject: [PATCH 2/8] Updated on 2026-08-14 --- .../datasource/local/preferences/PreferencesKeys.kt | 3 +++ .../data/notifications/DefaultNotificationsRepository.kt | 9 +++++++++ .../notifications/repository/NotificationsRepository.kt | 8 ++++++++ .../feature/wallet/child/wallet/model/WalletModel.kt | 9 ++++++++- 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt index 90230d2f23..a91cb3cf09 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt @@ -164,6 +164,9 @@ object PreferencesKeys { // region Permission fun getShouldShowPermission(permission: String) = booleanPreferencesKey("shouldShowPushPermission_$permission") + fun getShouldShowAskNotificationPermissionViaBs() = + booleanPreferencesKey("ShouldShowAskNotificationPermissionViaBs") + fun getShouldShowInitialPermissionScreen(permission: String) = booleanPreferencesKey("shouldShowInitialPushPermissionScreen_$permission") // endregion diff --git a/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt b/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt index 5795eed9b7..d8dd3053d7 100644 --- a/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt +++ b/data/notifications/src/main/java/com/tangem/data/notifications/DefaultNotificationsRepository.kt @@ -2,6 +2,7 @@ package com.tangem.data.notifications import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys +import com.tangem.datasource.local.preferences.PreferencesKeys.getShouldShowAskNotificationPermissionViaBs import com.tangem.datasource.local.preferences.utils.* import com.tangem.domain.notifications.repository.NotificationsRepository import kotlinx.coroutines.flow.Flow @@ -73,4 +74,12 @@ class DefaultNotificationsRepository @Inject constructor( ) } } + + override suspend fun shouldAskNotificationPermissionsViaBs(): Boolean { + return appPreferencesStore.getSyncOrDefault(getShouldShowAskNotificationPermissionViaBs(), false) + } + + override suspend fun setShouldAskNotificationPermissionsViaBs(shouldAsk: Boolean) { + appPreferencesStore.store(key = getShouldShowAskNotificationPermissionViaBs(), value = shouldAsk) + } } \ No newline at end of file diff --git a/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/NotificationsRepository.kt b/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/NotificationsRepository.kt index 00d20b0f04..887576ef52 100644 --- a/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/NotificationsRepository.kt +++ b/domain/notifications/src/main/java/com/tangem/domain/notifications/repository/NotificationsRepository.kt @@ -56,4 +56,12 @@ interface NotificationsRepository { suspend fun getWalletAutomaticallyEnabledList(): List suspend fun setNotificationsWasEnabledAutomatically(userWalletId: String) + + /** + * By default it is false cause for the first try to show should be skipped. Only should be shown on second time + * app launch. + */ + suspend fun shouldAskNotificationPermissionsViaBs(): Boolean + + suspend fun setShouldAskNotificationPermissionsViaBs(shouldAsk: Boolean) } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt index 639d9da483..84cea60e9f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt @@ -236,6 +236,7 @@ internal class WalletModel @Inject constructor( private fun subscribeOnPushNotificationsPermission() { modelScope.launch { + val shouldAskNotificationPermissionsViaBs = notificationsRepository.shouldAskNotificationPermissionsViaBs() val shouldShow = notificationsRepository.shouldShowSubscribeOnNotificationsAfterUpdate() val isBiometricsEnabled = shouldSaveUserWalletsSyncUseCase() val isHuaweiDevice = getIsHuaweiDeviceWithoutGoogleServicesUseCase() @@ -245,7 +246,13 @@ internal class WalletModel @Inject constructor( "isHuaweiDevice $isHuaweiDevice", ) if (!isBiometricsEnabled) return@launch - if (!shouldShow) return@launch + if (!shouldShow) { + return@launch + } + if (!shouldAskNotificationPermissionsViaBs) { + notificationsRepository.setShouldAskNotificationPermissionsViaBs(true) + return@launch + } delay(timeMillis = 1_800) From 06e726d9ad0f48c8e24765b71b39db16b3de051d Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 13 Oct 2025 19:03:20 +0300 Subject: [PATCH 3/8] Updated on 2026-08-14 --- .../common/ui/alerts/TransactionErrorAlertConverter.kt | 7 +++++++ gradle/tangem_dependencies.toml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorAlertConverter.kt b/common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorAlertConverter.kt index 4cfcfa7a2b..89855cf6ce 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorAlertConverter.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorAlertConverter.kt @@ -3,6 +3,7 @@ package com.tangem.common.ui.alerts import com.tangem.common.ui.alerts.models.AlertDemoModeUM import com.tangem.common.ui.alerts.models.AlertTransactionErrorUM import com.tangem.common.ui.alerts.models.AlertUM +import com.tangem.core.ui.R import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.transaction.error.SendTransactionError @@ -43,6 +44,12 @@ class TransactionErrorAlertConverter( cause = value.ex?.localizedMessage, onConfirmClick = { onFailedTxEmailClick(value.ex?.localizedMessage.orEmpty()) }, ) + is SendTransactionError.CreateAccountUnderfunded -> AlertTransactionErrorUM( + code = "", + cause = null, + causeTextReference = resourceReference(R.string.no_account_polkadot, wrappedList(value.amount)), + onConfirmClick = popBackStack, + ) else -> null } } diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 1a4d35961e..6722388347 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,7 +5,7 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.30-1269" +tangemBlockchainSdk = "releases-5.30-1273" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "releases-5.30-567" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From a6ec3453dd98239d56c3917e00ee85a6eaa18472 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 14 Oct 2025 19:52:46 +0500 Subject: [PATCH 4/8] Updated on 2026-08-14 --- .../ui/notifications/NotificationsFactory.kt | 18 +++- .../feeSelector/utils/FeeCalculationUtils.kt | 3 +- .../v2/send/confirm/model/SendConfirmModel.kt | 1 + .../notifications/model/NotificationsModel.kt | 90 ++++++++++--------- .../model/YieldSupplyNotificationsModel.kt | 1 + 5 files changed, 69 insertions(+), 44 deletions(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt index 87e98e25c4..4afee30930 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt @@ -44,10 +44,12 @@ object NotificationsFactory { } } + @Suppress("LongParameterList") fun MutableList.addFeeUnreachableNotification( tokenStatus: CryptoCurrencyStatus, coinStatus: CryptoCurrencyStatus, feeError: GetFeeError?, + dustValue: BigDecimal?, onReload: () -> Unit, onClick: (currency: CryptoCurrency) -> Unit, ) { @@ -70,7 +72,16 @@ object NotificationsFactory { ) is GetFeeError.BlockchainErrors.SuiOneCoinRequired -> add(NotificationUM.Sui.NotEnoughCoinForTokenTransaction) - is GetFeeError.DataError, + is GetFeeError.DataError -> when (feeError.cause) { + BlockchainSdkError.TransactionDustChangeError -> add( + NotificationUM.Error.MinimumAmountError( + amount = dustValue.format { crypto(tokenStatus.currency) }, + ), + ) + else -> add( + NotificationUM.Warning.NetworkFeeUnreachable(onReload), + ) + } is GetFeeError.UnknownError, -> add( NotificationUM.Warning.NetworkFeeUnreachable(onReload), @@ -358,6 +369,11 @@ object NotificationsFactory { is BlockchainSdkError.Solana.DestinationRentExemption -> addRentExemptionDestinationNotification( rentExemptionAmount = validationError.rentAmount, ) + is BlockchainSdkError.TransactionDustChangeError -> add( + NotificationUM.Error.MinimumAmountError( + amount = dustValue.format { crypto(cryptoCurrency) }, + ), + ) null, -> minAdaValue?.let { add( diff --git a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/subcomponents/feeSelector/utils/FeeCalculationUtils.kt b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/subcomponents/feeSelector/utils/FeeCalculationUtils.kt index 3c251c609b..3d2db932dc 100644 --- a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/subcomponents/feeSelector/utils/FeeCalculationUtils.kt +++ b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/subcomponents/feeSelector/utils/FeeCalculationUtils.kt @@ -21,9 +21,10 @@ object FeeCalculationUtils { isAmountSubtractAvailable: Boolean, cryptoCurrencyStatus: CryptoCurrencyStatus, amountValue: BigDecimal, - feeValue: BigDecimal, + feeValue: BigDecimal?, reduceAmountBy: BigDecimal, ): BigDecimal { + if (feeValue == null || feeValue.isZero()) return amountValue val balance = cryptoCurrencyStatus.value.amount ?: return amountValue val isFeeCoverage = checkFeeCoverage( isSubtractAvailable = isAmountSubtractAvailable, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt index 414a66531b..647af4a902 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt @@ -161,6 +161,7 @@ internal class SendConfirmModel @Inject constructor( fun updateState(state: SendUM) { _uiState.value = state + onFeeReload() updateConfirmNotifications() } diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt index 73649cccf8..23e1fec6c3 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt @@ -120,46 +120,8 @@ internal class NotificationsModel @Inject constructor( buildNotifications() } - private suspend fun buildNotifications() { - val notifications = buildList { - addFeeUnreachableNotification( - tokenStatus = cryptoCurrencyStatus, - coinStatus = feeCryptoCurrencyStatus, - feeError = notificationData.feeError, - onReload = params.callback::onFeeReload, - onClick = ::showTokenDetails, - ) - addDomainNotifications() - } - - notificationsUpdateTrigger.callbackHasError(notifications.any { it is NotificationUM.Error }) - - _uiState.value = notifications.toImmutableList() - } - - private fun showTokenDetails(currency: CryptoCurrency) { - appRouter.pop { isSuccess -> - if (isSuccess) { - appRouter.push( - AppRoute.CurrencyDetails( - userWalletId = userWalletId, - currency = currency, - ), - ) - } - } - } - - private suspend fun MutableList.addDomainNotifications() = with(notificationData) { - val balance = cryptoCurrencyStatus.value.amount ?: return - val feeValue = fee?.amount?.value ?: return - val isFeeCoverage = checkFeeCoverage( - isSubtractAvailable = isAmountSubtractAvailable, - balance = balance, - amountValue = amountValue, - feeValue = feeValue, - reduceAmountBy = reduceAmountBy, - ) + private suspend fun buildNotifications() = with(notificationData) { + val feeValue = fee?.amount?.value val sendingAmount = checkAndCalculateSubtractedAmount( isAmountSubtractAvailable = isAmountSubtractAvailable, cryptoCurrencyStatus = cryptoCurrencyStatus, @@ -180,6 +142,50 @@ internal class NotificationsModel @Inject constructor( feeCurrencyBalanceAfterTransaction = feeCurrencyBalanceAfterTransaction, ) + val notifications = buildList { + addFeeUnreachableNotification( + tokenStatus = cryptoCurrencyStatus, + coinStatus = feeCryptoCurrencyStatus, + feeError = notificationData.feeError, + dustValue = currencyCheck.dustValue, + onReload = params.callback::onFeeReload, + onClick = ::showTokenDetails, + ) + addDomainNotifications(currencyCheck = currencyCheck, sendingAmount = sendingAmount) + } + + notificationsUpdateTrigger.callbackHasError(notifications.any { it is NotificationUM.Error }) + + _uiState.value = notifications.toImmutableList() + } + + private fun showTokenDetails(currency: CryptoCurrency) { + appRouter.pop { isSuccess -> + if (isSuccess) { + appRouter.push( + AppRoute.CurrencyDetails( + userWalletId = userWalletId, + currency = currency, + ), + ) + } + } + } + + private suspend fun MutableList.addDomainNotifications( + currencyCheck: CryptoCurrencyCheck, + sendingAmount: BigDecimal, + ) = with(notificationData) { + val balance = cryptoCurrencyStatus.value.amount ?: return + val feeValue = fee?.amount?.value ?: return + val isFeeCoverage = checkFeeCoverage( + isSubtractAvailable = isAmountSubtractAvailable, + balance = balance, + amountValue = amountValue, + feeValue = feeValue, + reduceAmountBy = reduceAmountBy, + ) + addErrorNotifications( sendingAmount = sendingAmount, feeValue = feeValue, @@ -198,10 +204,10 @@ internal class NotificationsModel @Inject constructor( addInfoNotifications() } - private fun getFeeCurrencyBalanceAfterTx(sendingAmount: BigDecimal, feeValue: BigDecimal): BigDecimal? { + private fun getFeeCurrencyBalanceAfterTx(sendingAmount: BigDecimal, feeValue: BigDecimal?): BigDecimal? { val sendingCurrencyBalance = cryptoCurrencyStatus.value as? CryptoCurrencyStatus.Loaded val feeCurrencyBalance = feeCryptoCurrencyStatus.value as? CryptoCurrencyStatus.Loaded - if (feeCryptoCurrencyStatus.value !is CryptoCurrencyStatus.Loaded) return null + if (feeCryptoCurrencyStatus.value !is CryptoCurrencyStatus.Loaded || feeValue == null) return null return when { feeCryptoCurrencyStatus == cryptoCurrencyStatus -> sendingCurrencyBalance?.let { it.amount - sendingAmount - feeValue diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/model/YieldSupplyNotificationsModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/model/YieldSupplyNotificationsModel.kt index be0223b21d..464eaaec8b 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/model/YieldSupplyNotificationsModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/model/YieldSupplyNotificationsModel.kt @@ -68,6 +68,7 @@ internal class YieldSupplyNotificationsModel @Inject constructor( coinStatus = feeCryptoCurrencyStatus, feeError = data.feeError, onClick = ::openTokenDetails, + dustValue = null, onReload = params.callback::onFeeReload, ) } From 400ffe72159ec57f22c0fe16dd5c1933d053036d Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 15 Oct 2025 15:19:25 +0500 Subject: [PATCH 5/8] Updated on 2026-08-14 --- .../src/main/java/com/tangem/common/ui/footers/SendingText.kt | 2 +- .../src/main/java/com/tangem/core/ui/components/BottomFade.kt | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/footers/SendingText.kt b/common/ui/src/main/java/com/tangem/common/ui/footers/SendingText.kt index b2c89117fe..ba14042e47 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/footers/SendingText.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/footers/SendingText.kt @@ -52,7 +52,7 @@ fun SendingText(footerText: TextReference, modifier: Modifier = Modifier) { color = TangemTheme.colors.text.tertiary, modifier = Modifier .fillMaxWidth() - .padding(16.dp), + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp), ) } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/BottomFade.kt b/core/ui/src/main/java/com/tangem/core/ui/components/BottomFade.kt index 25342ebfdc..1bdae671ae 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/BottomFade.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/BottomFade.kt @@ -42,7 +42,7 @@ fun BottomFade(modifier: Modifier = Modifier, backgroundColor: Color = TangemThe fun Fade( modifier: Modifier = Modifier, backgroundColor: Color = TangemTheme.colors.background.secondary, - height: Dp = 40.dp, + height: Dp = 32.dp, ) { Box( modifier = modifier @@ -50,7 +50,6 @@ fun Fade( .height(height) .background( brush = Brush.verticalGradient( - endY = 100f, colors = listOf( Color.Transparent, backgroundColor, From 6b16af9f8be6c0013d7646e967875937e8aaf98d Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 15 Oct 2025 14:00:32 +0300 Subject: [PATCH 6/8] Updated on 2026-08-14 --- .../staking/impl/presentation/model/StakingModel.kt | 12 +++++++++++- .../ton/CompleteInitializeBottomSheetTransformer.kt | 13 ++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) 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 f32aabd0e3..54636113ff 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 @@ -16,12 +16,16 @@ import com.tangem.core.analytics.api.ParamsInterceptorHolder 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.share.ShareManager import com.tangem.core.navigation.url.UrlOpener +import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.format import com.tangem.core.ui.haptic.TangemHapticEffect import com.tangem.core.ui.haptic.VibratorHapticManager +import com.tangem.core.ui.message.DialogMessage +import com.tangem.features.staking.impl.R import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase @@ -140,6 +144,7 @@ internal class StakingModel @Inject constructor( private val urlOpener: UrlOpener, @DelayedWork private val coroutineScope: CoroutineScope, private val innerRouter: InnerStakingRouter, + private val messageSender: UiMessageSender, appRouter: AppRouter, ) : Model(), StakingClickIntents { @@ -999,7 +1004,12 @@ internal class StakingModel @Inject constructor( network = cryptoCurrencyStatus.currency.network, ).fold( ifLeft = { - stateController.update(DismissBottomSheetStateTransformer) + messageSender.send( + DialogMessage( + title = resourceReference(id = R.string.send_alert_transaction_failed_title), + message = resourceReference(id = R.string.common_unknown_error), + ), + ) }, ifRight = { stateController.update(CompleteInitializeBottomSheetTransformer( diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/CompleteInitializeBottomSheetTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/CompleteInitializeBottomSheetTransformer.kt index 7a9bc02057..b668a11791 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/CompleteInitializeBottomSheetTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/CompleteInitializeBottomSheetTransformer.kt @@ -10,6 +10,7 @@ import com.tangem.features.staking.impl.presentation.state.StakingUiState import com.tangem.features.staking.impl.presentation.state.bottomsheet.TonInitializeAccountBottomSheetConfig import com.tangem.utils.transformer.Transformer import java.math.BigDecimal +import java.math.RoundingMode internal class CompleteInitializeBottomSheetTransformer( private val cryptoCurrencyStatus: CryptoCurrencyStatus, @@ -21,8 +22,10 @@ internal class CompleteInitializeBottomSheetTransformer( val prevBottomSheetConfigContent = prevBottomSheetConfig.content as? TonInitializeAccountBottomSheetConfig ?: return prevState - val feeAmount = (prevBottomSheetConfigContent.feeState as? FeeState.Content) - ?.fee?.amount?.value?.multiply(BigDecimal(FEE_MULTIPLIER)) ?: return prevState + val feeAmount = (prevBottomSheetConfigContent.feeState as? FeeState.Content)?.fee?.amount ?: return prevState + + val multipliedFeeAmount = feeAmount.value?.multiply(BigDecimal(FEE_MULTIPLIER)) + ?.setScale(feeAmount.decimals, RoundingMode.HALF_DOWN) ?: return prevState val confirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data ?: return prevState @@ -31,12 +34,12 @@ internal class CompleteInitializeBottomSheetTransformer( cryptoCurrencyStatus = cryptoCurrencyStatus, minimumTransactionAmount = minimumTransactionAmount, value = ReduceByData( - feeAmount, - feeAmount, + multipliedFeeAmount, + multipliedFeeAmount, ), ).transform(prevState.amountState), confirmationState = confirmationState.copy( - reduceAmountBy = feeAmount, + reduceAmountBy = multipliedFeeAmount, ), bottomSheetConfig = prevBottomSheetConfig.copy( content = prevBottomSheetConfigContent.copy( From 338bb4732ba211925f93374d68a0581711e3a6d2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 15 Oct 2025 14:20:56 +0300 Subject: [PATCH 7/8] Updated on 2026-08-14 --- core/res/src/main/res/values-ja/strings.xml | 27 +++++--- core/res/src/main/res/values-ru/strings.xml | 67 ++++++++++++++++++- .../src/main/res/values-zh-rTW/strings.xml | 2 + core/res/src/main/res/values/strings.xml | 30 +++++---- gradle/tangem_dependencies.toml | 2 +- 5 files changed, 103 insertions(+), 25 deletions(-) diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 282551cd56..52be016eb1 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -504,7 +504,7 @@ エラーが発生しました。コード: %s 。 メモが必要 取引 - 選択したトークンの承認制限を指定します + 承認すると、このスマートコントラクトが今後の取引でトークンを利用できるようになります。 金額%s 承認機能は、別のアドレスに特定の量のトークンを使用する許可を与えるために必要です。設計上スマートコントラクトは、承認しない限りトークンにアクセスできません。トークンを「ロック解除」すると、StakeKitスマート コントラクトがトークンを使用する権限が与えられます。ネットワークのマイナーは、このアクションをブロックチェーンに記録するためにガス料金(あなたが支払う)を受け取ります。承認後、トークンをステーキングできます。 続行するには、Polygonスマートコントラクトが%sを使用することを許可する必要があります @@ -865,6 +865,7 @@ その他の通貨 人気の法定通貨 通貨で検索 + 最良のレートを取得しています... 即時 オンランプ機能を使用することにより、プロバイダの%1$sおよび%2$sに同意するものとします サービスは外部プロバイダーによって提供されます。 \nTangemは責任を負いません。 @@ -894,6 +895,7 @@ 最大%d日 %s分 + 下記より利用可能 以下が手に入ります。 サービスは外部プロバイダーによって提供されます。 \nTangemは責任を負いません。 この画面を閉じて、トークンの詳細画面で取引状況を確認できます。 @@ -1165,7 +1167,7 @@ 新しいバリデーターを使用して%1$sネットワークにステーキングすると、以前にステーキングされた資金がすべてこのバリデーターに自動的に転送されます。 獲得した報酬をステーキングに再投資し、潜在的な収益を増やします。 再ステーキングを使うと、ステーキングを解除することなく、あるバリデータから別のバリデータに資金を移動できます。 - 残高のすべてをステーキングしようとしています。ステーキング解除や報酬請求にかかるネットワーク手数料をカバーするために、少額を残しておくことをお勧めします。 + ウォレットの残高をすべてステーキングすると、ステーキング解除時にネットワーク手数料の支払いが必要になります。そのため、少額をウォレットに残しておくことをおすすめします。 ステーキングを始めるには、TONアカウントを1 TONの自己取引で有効化する必要があります。資金はウォレット内にそのまま残り、この手順でステーキング用にアカウントを有効化できます。 アカウントの有効化 TONのステーキングを開始するには、まず自分のアドレスに少額の取引を送信します。これによりウォレットが有効になります。 @@ -1275,6 +1277,8 @@ 利用不可 データの読み込みに失敗しました。しばらくしてからもう一度お試しください。 非表示 + 技術的な問題が検出されました。しばらくしてからもう一度お試しいただくか、サポートにお問い合わせください。 + 現在、受け取りは利用できません 表示 カードの詳細 アカウントを作成してカードを発行 @@ -1700,7 +1704,7 @@ %s XTZを減らす 次回ウォレットにチャージするときに手数料の増加を避けるには、金額を%s XTZ減らしてください。 資産残高に関するテキスト [プレースホルダー] - %sはAaveに預け入れられています + %sはAaveに預けられています 承認する 前回の承認に問題があったため、新しい承認が必要です。手続き方法を選択してください。 承認が必要 @@ -1711,7 +1715,7 @@ あなたの%sはAaveに預けられています チャートを読み込めません・・ 受け取った金額%1$s %2$sはAaveに入金されませんでした。 - %1$s%% を獲得 + 年利%1$s%% 利用可能 現在のAPY 私の資金 @@ -1725,7 +1729,10 @@ 今後の%sの入金はすべて、取引手数料が差し引かれて自動的にAaveに供給されます。 ネットワーク手数料が上限手数料を超えた場合、手数料が下がるまで取引は成立しません。この制限は後で変更できます。 最大手数料 + 取引手数料は、預入額の4%未満である必要があります。Tangemは、この条件を満たす十分な残高が貯まった時点で、Aaveへの資金移動を行います。 + 最低入金額 手数料ポリシー + Tangemはまた、得られた利回りに対して3%のサービス手数料を差し引きます。 ネットワーク手数料が現在高すぎます。設定した上限を下回るまで待機しています。 過去のリターン ここに説明を入力してください。1〜3行が理想的です。[プレースホルダー] @@ -1735,9 +1742,9 @@ アカウントへの入金はすべて自動的にAaveに貸し出されます。 残高は自動的に計算されます いつでも、即座に資金を送信、交換、売却できます。 - すぐに現金化 + いつでも資金にアクセス可能 使い方 - Aaveは世界中で何百万人もの人々に信頼されています。総貸付額は104億ドルです。 + Aaveは、総額819億ドル以上の資産を管理する分散型プロトコルです。 分散型・自己管理型 サービスを利用することにより、プロバイダー\n %1$sおよび%2$sに同意したことになります 年間%s%%の収益 @@ -1749,20 +1756,20 @@ 提供 金利は変動します 入金すると、資金は自動的にAaveに送金され、利息が付き始めます。取引手数料として%s相当の少額の手数料が差し引かれます。 - 利息の獲得を開始 + 資産を供給する %sはAaveに供給され、すぐに利用可能になります 手数料ポリシーを見る - 次回の入金は自動的にAaveに供給されます。 + 次回以降の入金は自動的にAaveに供給されます。 アクティブ 停止中 収益を停止する オフにすると、Aaveから資金が引き出され、ウォレットの%sに戻され、報酬の獲得が停止されます。 出金金額からネットワーク手数料が差し引かれます。 - 供給APR + 供給APY APY あなたの資産を眠らせない — 残高を運用して利息を得ましょう。 利息は自動的に発生します - Aaveレンディング + Aaveの利回り 入金の処理中 年間%1$s%%の収益 自動 diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index c55cacce85..e65d507051 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -202,6 +202,7 @@ Импортировать В процессе Позже + Узнать больше Осталось %1$s Заблокирован Основная сеть @@ -1547,6 +1548,7 @@ URI уже используется WalletConnect Подозрительная транзакция + Узнать больше и купить Отказаться Вы не закончили резервное копирование. Хотите продолжить? Да, возобновить @@ -1561,13 +1563,74 @@ Нет, отправить все Уменьшить на %s XTZ Чтобы не платить повышенную комиссию при следующем пополнении кошелька, уменьшите сумму на %s XTZ + Ваш %s внесён в Aave Выдать разрешение + Что-то пошло не так с вашим предыдущим разрешением, поэтому требуется новое. Выберите, как хотите продолжить. + Необходимо разрешение + Комиссия будет списана, и ваши активы снова начнут приносить доход. + Чтобы продолжить зарабатывать, нужно выдать разрешение. + Подтвердить разрешение + Ваш %s внесён в Aave Невозможно загрузить график Полученная сумма, %1$s %2$s, не была зачислена на Aave. - Сетевая комиссия сейчас слишком высокая. Ожидаем, пока она упадёт ниже вашего лимита. + APY %1$s%% + Доступно + Текущий APY + Мои средства + Ваш %1$s теперь внесён в Aave и приносит проценты. У вас есть токен %2$s, который отражает ваш баланс и со временем увеличивается. При пополнении средства автоматически направляются в Aave для получения процентов за вычетом комиссии за транзакцию. + Итоговый доход + Переводы в Aave + Изучите Aave + Это текущая комиссия в сети %s. + Текущая комиссия + Все следующие пополнения %s автоматически поступят в Aave с удержанием комиссии за транзакцию. + Если комиссия сети превысит максимальный лимит, транзакция не будет выполнена до тех пор, пока комиссия не снизится. Вы сможете изменить этот лимит позже. + Максимальная комиссия + Комиссия за транзакцию должна быть ниже 4% от суммы депозита. Tangem переведёт средства в Aave, как только это условие будет выполнено. + Минимальный депозит + Политика комиссий + Tangem взимает комиссию за обслуживание в размере 3% от полученного дохода. + Комиссия в сети сейчас слишком высокая. Ждём, пока она упадёт ниже вашего лимита. Историческая доходность + Необходимо разрешение для токена Проверьте ваше интернет соединение - Годовая доходность + Информация о комиссии недоступна + Каждое пополнение вашего адреса автоматически будет отправляться в Aave. + Ваш баланс работает автоматически + Отправляйте, обменивайте или продавайте свои средства мгновенно, когда захотите. + Мгновенный вывод средств + Как это работает? + Aave — это децентрализованный протокол, управляющий активами на сумму более 81,9 миллиарда долларов США. + Децентрализованный и некастодиальный + Используя сервис, вы соглашаетесь с условиями провайдера %1$s и %2$s + Зарабатывайте %s%% в год + Aave • Ставка с плавающим процентом + Aave + Среднее %s + Доходность за прошлый год + Текущая процентная ставка всегда переменная и автоматически рассчитывается смарт-контрактом AAVE в блокчейне на основе текущего спроса и предложения. + При поддержке + Ставка может меняться + При пополнении ваши средства автоматически отправляются в Aave для начала начисления процентов. Для покрытия комиссии с вас будет удержана небольшая плата в размере %s. + Начать зарабатывать + Ваш %s будет передан в Aave и останется всегда доступным. + Политика комиссий + Следующие пополнения вашего счёта автоматически поступят в Aave. + Активен + На паузе + Закончить зарабатывать + Выключив эту функцию, вы выведёте средства из Aave, получите их обратно в %s в кошельке и перестанете зарабатывать награды. + Комиссия сети будет вычтена из суммы вашего вывода. + Годовая доходность (APY) + APY + Пусть ваши деньги работают — зарабатывайте проценты на свой баланс. + Проценты начисляются автоматически. + Доходность Aave + Отправка ваших средств + Зарабатывайте %1$s%% в год + Автоматически + Внесите немного %1$s %2$s, чтобы покрыть комиссию сети за транзакции. + Невозможно покрыть комиссию в %s Сервис начисления процентов в данный момент недоступен. Пожалуйста, попробуйте позже. Данные о доходе недоступны Невозможно загрузить график diff --git a/core/res/src/main/res/values-zh-rTW/strings.xml b/core/res/src/main/res/values-zh-rTW/strings.xml index 713520796a..2e0760aa10 100644 --- a/core/res/src/main/res/values-zh-rTW/strings.xml +++ b/core/res/src/main/res/values-zh-rTW/strings.xml @@ -275,6 +275,7 @@ 掃描卡片 掃描卡片以更改其設置。這些更改只會影響您掃描過的卡,不會影響綁定到您錢包的其他卡。 準備好您的卡! + 安全警示: 數量 地址與錢包地址相同 最小數量是 %s @@ -338,6 +339,7 @@ 用 %s 解鎖全部 區塊鍊無法使用。稍後再試 掃描卡片 + 此钱包之前已被激活。\n如果不是您本人激活,请联系客服。\nTangem 绝不会出售附带预生成助记词的钱包。 請求籤署消息。%s Dapp %1$s,請求\n簽署 BNB 交易。\n%2$s %1$s 的交易訂單\n價格: %2$s\n接收金額:%3$s\n支付數量: %4$s diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 3e4c4ec8a8..258d009305 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -29,6 +29,7 @@ You are archiving this account, but you can always get it back. Account Account saved + Account for rewards Account #%s — used for address derivation. Add account Save @@ -512,7 +513,7 @@ An error occurred. Code: %s. Requires memo Transaction - Specify the approve limit for the selected token + By approving, you allow the smart contract to use your tokens in future transactions. Amount %s The Approve function is needed to grant permission to another address to use a specific amount of your tokens. By design, smart contracts can\'t access your tokens unless you approve. By \"unlocking\" your tokens, you authorize the StakeKit smart contract to use them. The network\'s miners receive a gas fee (paid by you) to record this action on the blockchain. You can stake your token after giving approval. To continue you need to allow Polygon smart contract to use your %s @@ -883,6 +884,7 @@ Other currencies Popular Fiats Search by currency + Fetching best rates... Instant By using onramp functionality, you agree with provider’s %1$s and %2$s Service is provided by an external provider.\nTangem is not responsible. @@ -914,6 +916,7 @@ up to %d days %s min + Available from You get Service is provided by an external provider. \nTangem is not responsible. You can close this screen and check the transaction status on the token details screen. @@ -1188,7 +1191,7 @@ Staking on the %1$s network with a new validator will automatically transfer all previously staked funds to this validator. Reinvests your earned rewards in your staked amount, increasing potential earnings. Restake lets you move your funds from one validator to another without the need to unstake - You’re about to stake your entire balance. We recommend leaving a small amount to cover network fees for unstaking or claiming rewards. + If you stake your entire balance, you’ll need to pay a network fee when you unstake. We recommend leaving a small amount in your wallet to cover network fees. To start staking, your TON account must be activated with a self-transaction of 1 TON. The funds stay in your wallet — this step only enables your account for staking. Account activation To start staking in TON, first send a small transaction to your own address — this will activate your wallet. @@ -1298,6 +1301,8 @@ not available Failed to load data. Try again later. Hide + Technical issues detected. Please try again later or contact support. + Receive unavailable now Reveal Card details Create account and issue a card @@ -1772,7 +1777,8 @@ Reduce by %s XTZ To avoid paying an increased commission the next time you top up your wallet, reduce the amount by %s XTZ Text about your money in balance [PLACEHOLDER] - Your %s is deposited in Aave + Your %s is deposited in Aave + The amount received, %1$s %2$s was not deposited to Aave. Give Approve Something went wrong with your previous approval, so we need a new one. Choose how you’d like to proceed. Approve needed @@ -1783,10 +1789,10 @@ Your %s is deposited in Aave Unable to load chart... The amount received, %1$s %2$s was not deposited to Aave. - Earn %1$s%% + APY %1$s%% Available Current APY - My Funds + My funds Your %1$s is now deposited in Aave and earning interest. You hold a%2$s token, which represents your balance and grows over time. When you top up, funds go to Aave to earn interest, minus a transaction fee. Earn Total earnings @@ -1798,7 +1804,7 @@ If network fees rise above maximum fee, the transaction won’t go through until they decrease. You can change this limit later. Maximum fee The transaction fee must stay below 4% of your deposit. Tangem will transfer funds to Aave only once your balance is large enough to meet this condition. - Minimal amount + Minimal top-up Fee policy Tangem also takes a 3% service fee on the yield earned. Network fee is too high right now. Waiting until it falls below your limit. @@ -1810,9 +1816,9 @@ Every top-up of your account will be lended to Aave automatically. Your balance works automatically Send, swap, or sell your funds instantly, anytime you want. - Cash out instantly + Access to funds at any time How it works? - Aave is trusted by millions worldwide. Total lended value is $10.4B. + Aave is a decentralized protocol managing over $81.9 billion in total value. Decentralized and self-custodial By using service, you agree with provider\n%1$s and %2$s Earn %s%% yearly @@ -1824,20 +1830,20 @@ Powered by Interest rate is variable When you top up, your funds will be automatically sent to Aave to start earning interest. A small fee equal to %s will be deducted to cover the transaction. - Start earning + Supply assets Your %s will be supplied to Aave and will stay instantly available See fee policy - Your next deposits will be automatically supplied to Aave. + Your next top-ups will be automatically supplied to Aave. Active Paused Stop earning Turning off will withdraw your funds from Aave, return them to %s in your wallet, and stop earning rewards. The network fee will be deducted from the amount you withdraw. - Supply APR + Supply APY APY Make your money work — earn interest on your balance. Interest accrues automatically - Aave lending + Aave yield Processing your deposit Earn %1$s%% per year Automatic diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 6722388347..d1245e4f75 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,7 +5,7 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.30-1273" +tangemBlockchainSdk = "releases-5.30-1282" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "releases-5.30-567" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From 6b5f634416d9168ce6490c6f395c5ffe133a8f2b Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 15 Oct 2025 11:21:16 +0000 Subject: [PATCH 8/8] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index d1245e4f75..4f616ee16e 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,9 +5,9 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.30-1282" +tangemBlockchainSdk = "develop-1275" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "releases-5.30-567" +tangemCardSdk = "develop-564" #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 ^