From 2ee3bce46a8b093e19ebaaaae9763e59e7d9498d Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 29 Oct 2025 13:06:43 +0300 Subject: [PATCH 01/19] Updated on 2026-08-14 --- .../domain/tasks/product/ScanProductTask.kt | 2 +- .../domain/twins/CreateFirstTwinWalletTask.kt | 2 +- .../twins/CreateSecondTwinWalletTask.kt | 2 +- .../tap/domain/twins/TwinCardsManager.kt | 78 -------- .../tap/domain/twins/TwinCardsWidget.kt | 174 ------------------ .../tangem/tap/domain/twins/WrongTwinCard.kt | 2 +- .../domain/card/common}/TwinsHelperTest.kt | 9 +- .../com/tangem/domain/common/TwinsHelper.kt | 90 --------- .../wallets/usecase/GetCardImageUseCase.kt | 4 +- .../v2/twin/impl/model/OnboardingTwinModel.kt | 14 +- tangem-android-tools | 2 +- 11 files changed, 22 insertions(+), 357 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt delete mode 100644 app/src/main/java/com/tangem/tap/domain/twins/TwinCardsWidget.kt rename {domain/card/src/test/java/com/tangem/domain/card => data/account/src/test/java/com/tangem/domain/card/common}/TwinsHelperTest.kt (86%) delete mode 100644 domain/legacy/src/main/java/com/tangem/domain/common/TwinsHelper.kt diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt index 45653eeeea..93a1c1f2be 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt @@ -19,7 +19,7 @@ import com.tangem.domain.card.common.TapWorkarounds.isNotSupportedInThatRelease import com.tangem.domain.card.common.TapWorkarounds.isStart2Coin import com.tangem.domain.card.common.TapWorkarounds.isTangemTwins import com.tangem.domain.card.common.TapWorkarounds.isVisa -import com.tangem.domain.common.TwinsHelper +import com.tangem.domain.card.common.TwinsHelper import com.tangem.domain.wallets.derivations.derivationStyleProvider import com.tangem.domain.card.common.visa.VisaUtilities import com.tangem.domain.card.configs.CardConfig diff --git a/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt index b7b896682c..659921880b 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt @@ -5,7 +5,7 @@ import com.tangem.common.card.EllipticCurve import com.tangem.common.core.CardSession import com.tangem.common.core.CardSessionRunnable import com.tangem.common.core.CompletionCallback -import com.tangem.domain.common.TwinsHelper +import com.tangem.domain.card.common.TwinsHelper import com.tangem.operations.attestation.AttestationTask import com.tangem.operations.wallet.CreateWalletResponse import com.tangem.operations.wallet.CreateWalletTask diff --git a/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt index b466017130..000cee1a09 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt @@ -8,7 +8,7 @@ import com.tangem.common.core.CardSession import com.tangem.common.core.CardSessionRunnable import com.tangem.common.core.CompletionCallback import com.tangem.common.extensions.hexToBytes -import com.tangem.domain.common.TwinsHelper +import com.tangem.domain.card.common.TwinsHelper import com.tangem.operations.wallet.CreateWalletResponse import com.tangem.operations.wallet.CreateWalletTask import com.tangem.operations.wallet.PurgeWalletCommand diff --git a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt deleted file mode 100644 index b503705f7e..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.tangem.tap.domain.twins - -import com.tangem.Message -import com.tangem.common.CompletionResult -import com.tangem.common.KeyPair -import com.tangem.common.extensions.hexToBytes -import com.tangem.common.extensions.toHexString -import com.tangem.domain.models.scan.CardDTO -import com.tangem.domain.models.scan.ScanResponse -import com.tangem.operations.wallet.CreateWalletResponse -import com.tangem.tap.common.extensions.inject -import com.tangem.tap.proxy.redux.DaggerGraphState -import com.tangem.tap.store -import com.tangem.tap.tangemSdkManager - -class TwinCardsManager(card: CardDTO) { - - private val issuersConfigStorage by lazy(mode = LazyThreadSafetyMode.NONE) { - store.inject(DaggerGraphState::issuersConfigStorage) - } - - private val firstCardId: String = card.cardId - private val publicKey: String = card.issuer.publicKey.toHexString() - - private var currentCardPublicKey: String? = null - private var secondCardPublicKey: String? = null - - suspend fun createFirstWallet(message: Message): CompletionResult { - val response = tangemSdkManager.createFirstTwinWallet(cardId = firstCardId, initialMessage = message) - - if (response is CompletionResult.Success) { - currentCardPublicKey = response.data.wallet.publicKey.toHexString() - } - - return response - } - - suspend fun createSecondWallet( - initialMessage: Message, - preparingMessage: Message, - creatingWalletMessage: Message, - ): CompletionResult { - val response = tangemSdkManager.createSecondTwinWallet( - firstPublicKey = requireNotNull(currentCardPublicKey), - firstCardId = firstCardId, - issuerKeys = getIssuerKeys(), - preparingMessage = preparingMessage, - creatingWalletMessage = creatingWalletMessage, - initialMessage = initialMessage, - ) - - if (response is CompletionResult.Success) { - secondCardPublicKey = response.data.wallet.publicKey.toHexString() - } - - return response - } - - suspend fun complete(message: Message): CompletionResult { - val response = tangemSdkManager.finalizeTwin( - secondCardPublicKey = requireNotNull(secondCardPublicKey).hexToBytes(), - issuerKeyPair = getIssuerKeys(), - cardId = firstCardId, - initialMessage = message, - ) - - return response - } - - private suspend fun getIssuerKeys(): KeyPair { - val issuer = issuersConfigStorage.getConfig().first { it.publicKey == publicKey } - - return KeyPair( - publicKey = issuer.publicKey.hexToBytes(), - privateKey = issuer.privateKey.hexToBytes(), - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsWidget.kt b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsWidget.kt deleted file mode 100644 index ca1f95a650..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsWidget.kt +++ /dev/null @@ -1,174 +0,0 @@ -package com.tangem.tap.domain.twins - -import android.animation.AnimatorSet -import android.animation.ObjectAnimator -import android.animation.PropertyValuesHolder -import android.view.View -import androidx.core.animation.doOnEnd -import com.tangem.common.extensions.VoidCallback -import com.tangem.domain.common.TwinCardNumber -import com.tangem.sdk.ui.widget.leapfrogWidget.LeapView -import com.tangem.sdk.ui.widget.leapfrogWidget.LeapViewState -import com.tangem.sdk.ui.widget.leapfrogWidget.LeapfrogWidget - -/** -[REDACTED_AUTHOR] - */ -class TwinsCardWidget( - val leapfrogWidget: LeapfrogWidget, - private val deviceScaleFactor: Float = 1f, - val getTopOfAnchorViewForActivateState: () -> Float, -) { - - var state: TwinCardsWidgetState? = null - private set - - private val animationDuration = 300L - - init { - if (leapfrogWidget.getViewsCount() != 2) throw UnsupportedOperationException() - } - - fun toWelcome(animate: Boolean = true, onEnd: VoidCallback = {}) { - if (state == TwinCardsWidgetState.Welcome) return - - state = TwinCardsWidgetState.Welcome - val animator = createAnimator(animate) - animator.playTogether( - createAnimator(TwinCardNumber.First, createWelcomeProperties(TwinCardNumber.First)), - createAnimator(TwinCardNumber.Second, createWelcomeProperties(TwinCardNumber.Second)), - ) - animator.doOnEnd { onEnd() } - leapfrogWidget.fold(animate) { animator.start() } - } - - fun toLeapfrog(animate: Boolean = true, onEnd: VoidCallback = {}) { - if (state == TwinCardsWidgetState.Leapfrog) return - - state = TwinCardsWidgetState.Leapfrog - val animator = createAnimator(animate) - animator.playTogether( - createAnimator(TwinCardNumber.First, createLeapfrogProperties(TwinCardNumber.First)), - createAnimator(TwinCardNumber.Second, createLeapfrogProperties(TwinCardNumber.Second)), - ) - animator.doOnEnd { - leapfrogWidget.initViews() - leapfrogWidget.unfold(animate, onEnd) - } - animator.start() - } - - fun toActivate(animate: Boolean = true, onEnd: VoidCallback = {}) { - if (state == TwinCardsWidgetState.Activate) return - - state = TwinCardsWidgetState.Activate - val animator = createAnimator(animate) - animator.playTogether( - createAnimator(TwinCardNumber.First, createActivateProperties(TwinCardNumber.First)), - createAnimator(TwinCardNumber.Second, createActivateProperties(TwinCardNumber.Second)), - ) - animator.doOnEnd { onEnd() } - animator.start() - } - - private fun createAnimator(animate: Boolean): AnimatorSet { - return AnimatorSet().apply { - duration = if (animate) animationDuration else 0 - } - } - - private fun createAnimator(cardNumber: TwinCardNumber, properties: TwinsCardProperties): ObjectAnimator { - val view = getLeapViewByCardNumber(cardNumber).view - val animator = ObjectAnimator.ofPropertyValuesHolder(view, *properties.createValuesHolders().toTypedArray()) - view.elevation = properties.elevation - return animator - } - - @Suppress("MagicNumber") - private fun createWelcomeProperties(cardNumber: TwinCardNumber): TwinsCardProperties { - return when (cardNumber) { - TwinCardNumber.First -> { - TwinsCardProperties( - xTranslation = -120f * deviceScaleFactor, - yTranslation = -220f * deviceScaleFactor, - rotation = -3f, - elevation = 1f, - scale = deviceScaleFactor, - ) - } - TwinCardNumber.Second -> { - TwinsCardProperties( - xTranslation = 170f * deviceScaleFactor, - yTranslation = 170f * deviceScaleFactor, - rotation = -3f, - elevation = 0f, - scale = deviceScaleFactor, - ) - } - } - } - - private fun createLeapfrogProperties(cardNumber: TwinCardNumber): TwinsCardProperties { - val twinProperties = TwinsCardProperties.from(getLeapViewByCardNumber(cardNumber).state) - return twinProperties.copy( - xTranslation = 0f, - yTranslation = 0f, - rotation = 0f, - scale = 1f, - ) - } - - @Suppress("MagicNumber") - private fun createActivateProperties(cardNumber: TwinCardNumber): TwinsCardProperties { - val topOfAnchorView = getTopOfAnchorViewForActivateState() - val twinProperties = TwinsCardProperties.from(getLeapViewByCardNumber(cardNumber).state) - return twinProperties.copy( - xTranslation = twinProperties.xTranslation, - yTranslation = twinProperties.yTranslation - topOfAnchorView, - rotation = 0f, - scale = (twinProperties.scale - 0.5f) * deviceScaleFactor, - ) - } - - private fun getLeapViewByCardNumber(cardNumber: TwinCardNumber): LeapView { - return when (cardNumber) { - TwinCardNumber.First -> leapfrogWidget.getViewByPosition(0) - TwinCardNumber.Second -> leapfrogWidget.getViewByPosition(1) - } - } -} - -enum class TwinCardsWidgetState { - Welcome, Leapfrog, Activate -} - -private data class TwinsCardProperties( - val xTranslation: Float = 0f, - val yTranslation: Float = 0f, - val rotation: Float = 0f, - val elevation: Float = 0f, - val scale: Float = 1.1f, -) { - - fun createValuesHolders(): List { - return listOf( - PropertyValuesHolder.ofFloat(View.TRANSLATION_X, xTranslation), - PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, yTranslation), - PropertyValuesHolder.ofFloat(View.ROTATION, rotation), - PropertyValuesHolder.ofFloat(View.SCALE_X, scale), - PropertyValuesHolder.ofFloat(View.SCALE_Y, scale), - ) - } - - companion object { - fun from(leapViewState: LeapViewState): TwinsCardProperties { - val leapViewProperties = leapViewState.properties - - return TwinsCardProperties( - yTranslation = leapViewProperties.yTranslation, - elevation = leapViewProperties.elevationEnd, - scale = leapViewProperties.scale, - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/twins/WrongTwinCard.kt b/app/src/main/java/com/tangem/tap/domain/twins/WrongTwinCard.kt index d05d28217e..6752cb5cca 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/WrongTwinCard.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/WrongTwinCard.kt @@ -1,7 +1,7 @@ package com.tangem.tap.domain.twins import com.tangem.common.core.TangemError -import com.tangem.domain.common.TwinCardNumber +import com.tangem.domain.card.common.TwinCardNumber import com.tangem.tap.tangemSdkManager import com.tangem.wallet.R diff --git a/domain/card/src/test/java/com/tangem/domain/card/TwinsHelperTest.kt b/data/account/src/test/java/com/tangem/domain/card/common/TwinsHelperTest.kt similarity index 86% rename from domain/card/src/test/java/com/tangem/domain/card/TwinsHelperTest.kt rename to data/account/src/test/java/com/tangem/domain/card/common/TwinsHelperTest.kt index 76e2291eac..a45be46828 100644 --- a/domain/card/src/test/java/com/tangem/domain/card/TwinsHelperTest.kt +++ b/data/account/src/test/java/com/tangem/domain/card/common/TwinsHelperTest.kt @@ -1,9 +1,8 @@ -package com.tangem.domain.card +package com.tangem.domain.card.common -import com.tangem.domain.common.TwinsHelper -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue +import org.junit.Assert import org.junit.Test +import org.junit.jupiter.api.Assertions.* class TwinsHelperTest { @@ -19,7 +18,7 @@ class TwinsHelperTest { @Test fun `twins compatibility pack 1 success`() { - assertTrue(TwinsHelper.isTwinsCompatible(pack1Twins[0], pack1Twins[1])) + Assert.assertTrue(TwinsHelper.isTwinsCompatible(pack1Twins[0], pack1Twins[1])) assertTrue(TwinsHelper.isTwinsCompatible(pack1Twins[1], pack1Twins[0])) } diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/TwinsHelper.kt b/domain/legacy/src/main/java/com/tangem/domain/common/TwinsHelper.kt deleted file mode 100644 index c30c02b77c..0000000000 --- a/domain/legacy/src/main/java/com/tangem/domain/common/TwinsHelper.kt +++ /dev/null @@ -1,90 +0,0 @@ -package com.tangem.domain.common - -import com.tangem.crypto.CryptoUtils -import com.tangem.domain.models.scan.CardDTO - -object TwinsHelper { - - /** - * Card compatibility - * cb61 <-> cb62 - * cb64 <-> cb65 - * - */ - private const val FIRST_CARD_FIRST_SERIES = "CB61" - private const val SECOND_CARD_FIRST_SERIES = "CB62" - private const val FIRST_CARD_SECOND_SERIES = "CB64" - private const val SECOND_CARD_SECOND_SERIES = "CB65" - - @Suppress("MagicNumber") - fun verifyTwinPublicKey(issuerData: ByteArray, cardWalletPublicKey: ByteArray?): Boolean { - if (issuerData.size < 65 || cardWalletPublicKey == null) return false - - val publicKey = issuerData.sliceArray(0 until 65) - val signedKey = issuerData.sliceArray(65 until issuerData.size) - return CryptoUtils.verify(cardWalletPublicKey, publicKey, signedKey) - } - - fun getTwinCardNumber(cardId: String): TwinCardNumber? { - val isFirstCard = cardId.startsWith(FIRST_CARD_FIRST_SERIES) || - cardId.startsWith(FIRST_CARD_SECOND_SERIES) - if (isFirstCard) return TwinCardNumber.First - - val isSecondCard = cardId.startsWith(SECOND_CARD_FIRST_SERIES) || - cardId.startsWith(SECOND_CARD_SECOND_SERIES) - if (isSecondCard) return TwinCardNumber.Second - return null - } - - @Suppress("MagicNumber") - fun getTwinCardIdForUser(cardId: String): String { - if (cardId.length < 16) return cardId - - val twinCardId = cardId.substring(11..14) - val twinCardNumber = getTwinCardNumber(cardId)?.number ?: 1 - return "$twinCardId #$twinCardNumber" - } - - /** - * Twins compatibility - * cb61 <-> cb62 - * cb64 <-> cb65 - */ - fun isTwinsCompatible(firstCardId: String, secondCardId: String): Boolean { - return secondCardId.startsWith(getCompatibleTwinCardId(firstCardId)) - } - - private fun getCompatibleTwinCardId(cardId: String): String { - return when { - cardId.startsWith(FIRST_CARD_FIRST_SERIES) -> SECOND_CARD_FIRST_SERIES - cardId.startsWith(FIRST_CARD_SECOND_SERIES) -> SECOND_CARD_SECOND_SERIES - cardId.startsWith(SECOND_CARD_FIRST_SERIES) -> FIRST_CARD_FIRST_SERIES - cardId.startsWith(SECOND_CARD_SECOND_SERIES) -> FIRST_CARD_SECOND_SERIES - else -> { - "unknown" - } - } - } -} - -enum class TwinCardNumber(val number: Int) { - First(1), Second(2); - - fun pairNumber(): TwinCardNumber = when (this) { - First -> Second - Second -> First - } -} - -@Deprecated("Use ScanResponse.isTangemTwin") -fun CardDTO.isTangemTwin(): Boolean { - return TwinsHelper.getTwinCardNumber(cardId) != null -} - -fun CardDTO.getTwinCardNumber(): TwinCardNumber? { - return TwinsHelper.getTwinCardNumber(this.cardId) -} - -fun CardDTO.getTwinCardIdForUser(): String { - return TwinsHelper.getTwinCardIdForUser(this.cardId) -} \ No newline at end of file diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetCardImageUseCase.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetCardImageUseCase.kt index dbee9b5cfb..5e7d46dafe 100644 --- a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetCardImageUseCase.kt +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GetCardImageUseCase.kt @@ -2,8 +2,8 @@ package com.tangem.domain.wallets.usecase import com.tangem.common.card.FirmwareVersion import com.tangem.common.services.Result -import com.tangem.domain.common.TwinCardNumber -import com.tangem.domain.common.TwinsHelper +import com.tangem.domain.card.common.TwinCardNumber +import com.tangem.domain.card.common.TwinsHelper import com.tangem.domain.models.ArtworkModel import com.tangem.domain.wallets.models.Artwork import com.tangem.operations.attestation.ArtworkSize diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/twin/impl/model/OnboardingTwinModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/twin/impl/model/OnboardingTwinModel.kt index ab86ceed99..f1559c092d 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/twin/impl/model/OnboardingTwinModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/twin/impl/model/OnboardingTwinModel.kt @@ -16,9 +16,9 @@ import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.toWrappedList import com.tangem.datasource.local.config.issuers.IssuersConfigStorage +import com.tangem.domain.card.common.TwinCardNumber +import com.tangem.domain.card.common.getTwinCardNumber import com.tangem.domain.card.repository.CardRepository -import com.tangem.domain.common.TwinCardNumber -import com.tangem.domain.common.getTwinCardNumber import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.models.scan.ScanResponse @@ -68,6 +68,7 @@ internal class OnboardingTwinModel @Inject constructor( private val params = paramsContainer.require() private val firstCardTwinNumber = params.scanResponse.card.getTwinCardNumber() ?: error("Not twin") private val cryptoCurrencyStatusJobHolder = JobHolder() + private var twinCardsIds = Pair(null, null) private val _uiState = MutableStateFlow( when (params.mode) { @@ -159,6 +160,7 @@ internal class OnboardingTwinModel @Inject constructor( } is CompletionResult.Success -> { if (params.mode == Mode.CreateWallet) { + twinCardsIds = twinCardsIds.copy(first = result.data.cardId) cardRepository.startCardActivation(result.data.cardId) } @@ -216,6 +218,7 @@ internal class OnboardingTwinModel @Inject constructor( } is CompletionResult.Success -> { if (params.mode == Mode.CreateWallet) { + twinCardsIds = twinCardsIds.copy(second = result.data.cardId) cardRepository.startCardActivation(result.data.cardId) } @@ -299,7 +302,12 @@ internal class OnboardingTwinModel @Inject constructor( return@coroutineScope } - cardRepository.finishCardActivation(params.scanResponse.card.cardId) + twinCardsIds.first?.let { + cardRepository.finishCardActivation(it) + } + twinCardsIds.second?.let { + cardRepository.finishCardActivation(it) + } params.modelCallbacks.onDone() } diff --git a/tangem-android-tools b/tangem-android-tools index b64f8659fc..193db8a024 160000 --- a/tangem-android-tools +++ b/tangem-android-tools @@ -1 +1 @@ -Subproject commit b64f8659fce65e7749d50923b32bfad13e6b8cac +Subproject commit 193db8a0247a1f33574dcdd5f9ec4dab2c28ea73 From 9b6a954ed0245a191aa08ba7b08c8a8ed631e01f Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 29 Oct 2025 19:01:28 +0300 Subject: [PATCH 02/19] Updated on 2026-08-14 --- core/res/src/main/res/values-de/strings.xml | 74 ++++++-- core/res/src/main/res/values-es/strings.xml | 82 +++++++++ core/res/src/main/res/values-fr/strings.xml | 86 +++++++++- core/res/src/main/res/values-ja/strings.xml | 143 ++++++++++++---- core/res/src/main/res/values-ru/strings.xml | 90 +++++++++- .../src/main/res/values-uk-rUA/strings.xml | 80 +++++++++ .../src/main/res/values-zh-rTW/strings.xml | 2 + core/res/src/main/res/values/strings.xml | 162 +++++++++++++----- .../res/drawable/img_visa_waitlist_promo.webp | Bin 0 -> 13438 bytes .../data/promo/DefaultPromoRepository.kt | 17 +- .../tangem/domain/promo/models/PromoBanner.kt | 1 + .../promo/ShouldShowPromoWalletUseCase.kt | 5 +- .../intents/WalletWarningsClickIntents.kt | 36 ++-- .../analytics/WalletScreenAnalyticsEvent.kt | 6 + .../utils/WalletWarningsAnalyticsSender.kt | 1 + .../domain/GetMultiWalletWarningsFactory.kt | 17 +- .../wallet/state/model/WalletNotification.kt | 17 ++ .../ui/YieldSupplyDepositedWarningContent.kt | 2 +- gradle/tangem_dependencies.toml | 2 +- .../providers/ProviderTypeIdMapping.kt | 2 +- tangem-android-tools | 2 +- 21 files changed, 705 insertions(+), 122 deletions(-) create mode 100644 core/ui/src/main/res/drawable/img_visa_waitlist_promo.webp diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index 522132b11b..cec83f8e76 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -262,7 +262,7 @@ Importieren In Arbeit Später - Mehr erfahren + Mehr erfahren %1$s übrig Legacy Bitcoin Gesperrt @@ -337,7 +337,7 @@ Transaktion fehlgeschlagen Transaktionsstatus Transaktionen - Überweisung + Überweiseung Die Daten konnten nicht geladen werden… Ich verstehe Es ist ein Fehler aufgetreten. Bitte versuche es erneut. @@ -760,6 +760,8 @@ Krypto kaufen Profitiere von **0 % Gebühren** beim Kauf von Kryptowährungen per SEPA-Überweisung. Krypto mit SEPA kaufen + Trage dich in die Warteliste ein und erhalte eine Zahlungskarte, die es so noch nie gab. + Tangem Visa Card Du musst einen einzigen Zugangscode einrichten, um alle deine Geräte zu schützen Schützen Du kannst später auf jeder Karte oder Ring einen individuellen Zugangscode einrichten @@ -1200,7 +1202,7 @@ Monatlich Wöchentlich Belohnungen - Belohnungen auf Solana werden automatisch Deinem Staking-Guthaben hinzugefügt und können nicht separat angezeigt werden. + Belohnungen auf Solana werden automatisch Deinem Staking-Guthaben hinzugefügt und können nicht separat angezeigt werden. Stake gesperrt Mehr staken Beim Staking %1$s wird Dein gesamtes %2$s -Guthaben eingesetzt. Alle weiteren %2$s due Du in Deine Tangem-Wallet einzahlst, werden ebenfalls automatisch eingesetzt. @@ -1362,7 +1364,7 @@ Frühzeitiger Zugriff auf neue Funktionen und exklusive Angebote. Updates zu Funktionen und Neuigkeiten Möchtest du Push-Benachrichtigungen verwenden? - Aktiviere Push-Benachrichtigungen und wir benachrichtigen Dich sofort, wenn Gelder eintreffen \n + Aktiviere Push-Benachrichtigungen und wir benachrichtigen Dich sofort, wenn Gelder eintreffen Verpasse keine Transaktion Neues Wallet hinzufügen Möchtest Du diese Wallet wirklich entfernen? @@ -1675,30 +1677,80 @@ Nein, alles senden Um %s XTZ reduziert Damit Sie beim nächsten Aufladen Ihrer Brieftasche keine erhöhte Provision zahlen, soll der Betrag um %s XTZ reduziert werden + Wenn der Yield-Modus aktiviert ist, gehen alle zukünftigen Einzahlungen an diese Adresse an Aave. Du kannst über Dein Guthaben weiterhin frei verfügen. + Deine %s wird an Aave übermittelt + Die Bereitstellung von %1$s %2$s für Aave steht aus + Genehmigen + Die Genehmigung Deines Tokens wurde widerrufen. Erteilen diese erneut, um die Servicefunktionalität fortzusetzen. + Genehmigung erforderlich + Die Gebühr wird abgezogen und Dein Vermögen wird erneut verliehen. + Um weiterhin Geld verdienen zu können, ist eine Genehmigung erforderlich. + Genehmigung bestätigen + Deine Gelder werden derzeit dem Aave-Protokoll bereitgestellt, Du kannst sie jedoch jederzeit verwalten. + Deine%s ist in Aave hinterlegt Chart konnte nicht geladen werden... Der erhaltene Betrag %1$s %2$s wurde nicht auf Aave eingezahlt. + APY %1$s%% + Verfügbar + Aktueller effektiver Jahreszins + Beim Aufladen zum Ausleihen wird eine Netzwerkgebühr von maximal %1$s vom Guthaben abgezogen. + Die Netzwerkgebühr ist derzeit zu hoch, um die Kreditvergabe durchzuführen. Die Mittel werden bereitgestellt, sobald sie auf %1$s oder darunter fallen. + Meine Mittel + Dein %1$s ist nun bei Aave hinterlegt und bringt Zinsen ein. Du besitzt einen %2$s-Token, der Dein Guthaben repräsentiert und mit der Zeit wächst. Wenn Du mehr Geld einzahlst, wird dieses an Aave weitergeleitet, um Zinsen abzüglich einer Transaktionsgebühr zu erwirtschaften. + Ertragsmodus + Gesamtverdienst + Übertragungen zu Aave + Entdecke Aave + Dies ist die aktuelle Liefergebühr auf %s. Die tatsächlichen Kosten werden auf der Registerkarte \"Aktivierung\" angezeigt. Aktuelle Gebühr + Alle zukünftigen %s-Einzahlungen werden automatisch an Aave geliefert, wobei die Transaktionsgebühr abgezogen wird. + Bei jeder zukünftigen Aufladung wird eine Netzwerkgebühr von ungefähr %1$s (%2$s) abgezogen, die Ihr Limit von %3$s (%4$s) nicht überschreitet. + Wenn die Netzwerkgebühren über die maximale Gebühr steigen, wird die Transaktion erst durchgeführt, wenn diese sinken. Du kannst dieses Limit später ändern. Maximale Gebühr + Der Mindestbetrag wird aus der aktuellen Netzwerkgebühr berechnet, um sicherzustellen, dass er 4%% nicht überschreitet, was den Mindestbetrag %1$s (%2$s) ergibt. + Mindestaufladung Gebührenpolitik - Die Netzwerkgebühr ist derzeit zu hoch. Warte, bis sie unter Dein Limit fällt. + Tangem erhebt außerdem eine Servicegebühr von 15% auf den erzielten Ertrag. + Deine Gelder werden automatisch an Aave überwiesen, sobald die Netzwerkgebühren niedriger sind oder Dein Guthaben den erforderlichen Mindestbetrag erreicht. Historische Renditen - Sofortige Auszahlung + Die Freigabe für Deine Token im Yield-Modus wurde widerrufen. Öffne den Token, um die Berechtigung erneut zu erteilen. + Token-Genehmigung erforderlich + Prüfe Deine Netzwerkverbindung + Informationen zu den Netzwerkgebühren nicht erreichbar + Jede Einzahlung, die Du tätigst, wird automatisch an Aave weitergeleitet. + Automatische Übertragung zu Aave + Senden, tauschen oder verkaufen Deine Gelder sofort, wann immer Du willst. + Jederzeit Zugriff auf Dein Geld Wie funktioniert das? - Verdiene %s%% jährlich - Aave • Variabler Zinssatz + Aave ist ein dezentrales Protokoll, das einen Gesamtwert von über 61 Milliarden US-Dollar verwaltet. + Dezentral und selbstverwahrend + Durch die Nutzung dieses Dienstes erklärst Du Dich mit provider\n%1$s und %2$s einverstanden + Mit Aave verbinden + Aave %1$s%% • Variabler Zinssatz Aave Durchschnitt %s Renditen des letzten Jahres + Der aktuelle Zinssatz ist immer variabel und wird automatisch vom Aave On-Chain-Smart-Contract auf der Grundlage von Angebot und Nachfrage in Echtzeit berechnet. Unterstützt durch Der Zinssatz ist variabel + Wenn Du dein Guthaben auflädst, wird es automatisch an Aave weitergeleitet, um Zinsen zu verdienen. zur Deckung der Transaktionsgebühr wird ein Betrag von %s abgezogen. Beginn des Verdienstes + Dein %s wird an Aave übermittelt, bleibt aber verwaltbar. Siehe Gebührenrichtlinie + Deine nächste Aufladung wird automatisch an Aave weitergeleitet. Aktiv Pausiert + Deaktiviere den Yield-Modus + Wenn Du diese Option deaktivierst, wird Dein Geld von Aave auf %s in Deiner Wallet abgehoben und es werden keine Belohnungen mehr verdient. + Die Netzwerkgebühr wird von dem Betrag, den Du abhebst, abgezogen. Effektiver Jahreszins für Versorgung - Lass Dein Geld arbeiten – verdiene Zinsen auf Dein Guthaben. - Verdienst auf Dein Guthaben - Verdienen %1$s%% pro Jahr + Effektiver Jahreszins + Zinsen fallen automatisch an + Ertragsmodus + Bearbeitung Deiner Einzahlung + Automatisch + Einzahlung von %1$s %2$s zur Deckung der Netzwerkgebühr für Transaktionen + Die Gebühr %s kann nicht gedeckt werden Der Stakingservice ist derzeit nicht verfügbar. Bitte versuche es später erneut. Einnahmen nicht verfügbar Chart konnte nicht geladen werden... diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml index dcce73dd3a..a9f9168d50 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -653,6 +653,8 @@ Comprar cripto Disfrute de unas comisiones del **0%** al comprar criptomonedas mediante transferencias SEPA. Comprar criptomonedas con SEPA + Únete a la lista de espera y consigue una tarjeta de pago como ninguna otra. + Tangem Visa Card Configure un código de acceso único para proteger todos sus dispositivos. Proteger Puede configurar un código de acceso individual en cada tarjeta más adelante @@ -1106,6 +1108,7 @@ Compatible con Web 3.0 Se requiere una transacción entrante de al menos %1$s para proceder Fondos insuficientes + Al aprobar, permites que el contrato inteligente use tus tokens en futuras transacciones. Tasa Fija La red cobrará una tasa de aprobación del token para verificar que usted autoriza el uso de su token para el intercambio. Intercambie más tokens a mejores tasas directamente en su billetera. @@ -1212,6 +1215,8 @@ Acceso anticipado a nuevas funciones y ofertas exclusivas. Actualizaciones de características y noticias ¿Quiere utilizar\nnotificaciones push? + Active las notificaciones push y le avisaremos al instante cuando le lleguen fondos. + No se pierda ninguna transacción Agregar una nueva billetera ¿Estás seguro de que deseas olvidar esta billetera? Ha ocurrido un error, por favor escanee su tarjeta o anillo para iniciar sesión @@ -1398,6 +1403,7 @@ Tenemos algún tipo de problema Todas las dApps desconectadas Permitir gastar + Al aprobar, permites que la dApp o el contrato inteligente utilicen los tokens en futuras transacciones. Dirección Conectar Cargando @@ -1472,4 +1478,80 @@ No, enviar todo Reducir en %s XTZ Para evitar pagar una comisión mayor la próxima vez que recargue su billetera, reduzca el importe en %s XTZ + Con el modo Rendimiento activo, todos los depósitos futuros a esta dirección irán a Aave. Puede seguir gestionando sus fondos libremente. + Su %s se suministra a Aave + El suministro de %1$s %2$s a Aave está pendiente + Aprobar + Se ha revocado la aprobación de su token. Concédalo de nuevo para reanudar el servicio. + Aprobación necesaria + Se le descontará la comisión y se le volverán a prestar sus activos. + Para seguir ganando, se requiere aprobación. + Confirmar aprobación + Sus fondos se suministran actualmente al protocolo Aave, pero puede gestionarlos en cualquier momento. + Su %s está depositado en Aave + No se puede cargar el gráfico... + La cantidad recibida, %1$s %2$s no fue suministrada a Aave. + APY %1$s%% + Disponible + APY actual + En las recargas para préstamos, se deducirá del saldo una comisión de red no superior a %1$s. + La tasa de red es actualmente demasiado alta para ejecutar préstamos. Los fondos se suministrarán una vez que baje a %1$s o menos. + Mis fondos + Su %1$s está ahora depositado en Aave y devenga intereses. Tiene un token%2$s, que representa su saldo y crece con el tiempo. Cuando deposite más fondos, estos se suministrarán a Aave para ganar intereses, menos una comisión por transacción. + Modo de rendimiento + Ganancias totales + Transferencias a Aave + Explore Aave + Esta es la tarifa de suministro actual en %s. El coste real se mostrará en la pestaña de activación. + Tarifa actual + Todos los depósitos futuros %s se proporcionarán a Aave automáticamente, con la tarifa de transacción deducida. + Se deducirá una comisión de red aproximada de %1$s (%2$s) de cada recarga futura, y no superará su límite de %3$s (%4$s). + Si las tarifas de red superan la tarifa máxima, la transacción no se realizará hasta que disminuyan. Puede cambiar este límite más adelante. + Tarifa máxima + El monto mínimo se calcula a partir de la tarifa de red actual para garantizar que no exceda 4%%, lo que hace que el mínimo sea %1$s (%2$s). + Recarga mínima + Política de tarifas + Tangem también cobra una comisión de servicio del 15% sobre el rendimiento obtenido. + Sus fondos se suministrarán automáticamente a Aave una vez que las comisiones de red sean más bajas o su saldo alcance el importe mínimo requerido. + Rendimientos históricos + Se ha revocado la autorización para su token en el modo Rendimiento. Abra el token para volver a conceder el permiso. + Se necesita la aprobación de Token + Compruebe su conexión de red + Información de tarifas de red inaccesible + Cada depósito que realice se suministrará a Aave automáticamente. + Transferencia automática a Aave + Envíe, intercambie o venda sus fondos al instante, cuando quiera. + Acceda a sus fondos en cualquier momento + ¿Cómo funciona? + Aave es un protocolo descentralizado que administra más de 61 billones de dólares en valor total. + Descentralizado y autocustodiado + Al utilizar este servicio, usted acepta que el proveedor\n%1$s y %2$s + Conectar Aave + Aave %1$s%% - Tipo de interés variable + Aave + Promedio %s + Resultados del año pasado + La tasa de interés actual siempre es variable y calculada automáticamente por el contrato inteligente onchain de Aave, en función de la oferta y la demanda en tiempo real. + Desarrollado por + El tipo de interés es variable + Cuando recargue, sus fondos se enviarán automáticamente a Aave para comenzar a ganar intereses. %s se deducirá para cubrir la tarifa de transacción. + Suministro de activos + Su %s se suministrará a Aave, pero seguirá siendo gestionable. + Ver política de tarifas + Sus próximas recargas se suministrarán automáticamente a Aave. + Activo + En pausa + Desactivar el modo de rendimiento + Al desactivar esto, retirará sus fondos de Aave a %s en su billetera y dejará de ganar recompensas. + La comisión de red se deducirá del importe que retire. + Suministro APY + APY + Los intereses se devengan automáticamente + Modo de rendimiento + Procesando su depósito + Automático + Deposite algo de %1$s %2$s para cubrir la tarifa de red para las transacciones + No se puede cubrir la tarifa %s + El servicio de intereses no está disponible en este momento. Vuelva a intentarlo más tarde. + Ganancias no disponibles diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index 004c7dd622..ef9f1f5500 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -244,7 +244,7 @@ La transaction a échoué Statut de la transaction Transactions - Transfert + Fourniture Je comprends Il y avait une erreur. Veuillez réessayer. Inaccessible @@ -626,6 +626,8 @@ Acheter crypto Profitez de **0% de frais** lors de l\'achat de cryptomonnaies via des virements SEPA. Acheter des cryptomonnaies avec SEPA + Rejoignez la liste d’attente et obtenez une carte de paiement pas comme les autres. + Tangem Visa Card Vous devez définir un seul code d\'accès pour protéger tous vos appareils. Protéger Vous pourrez définir un code d\'accès individuel sur chaque carte plus tard @@ -1080,6 +1082,7 @@ Compatible avec Web 3.0 Une transaction entrante d\'au moins de %1$s est requise pour continuer Fonds insuffisants + En approuvant, vous autorisez le contrat intelligent à utiliser vos jetons dans de futures transactions. Taux fixe Le réseau facturera des frais d\'approbation de jeton pour vérifier que vous autorisez l\'utilisation de votre jeton pour l\'échange. Échangez plus de jetons à de meilleurs taux directement dans votre portefeuille. @@ -1185,6 +1188,8 @@ Accès anticipé à de nouvelles fonctionnalités et à des offres exclusives. Actualités et mises à jour Souhaitez-vous utiliser les\nnotifications push? + Activez les notifications pour recevoir des alertes lorsque des fonds arrivent dans votre portefeuille. + Ne manquez aucune transaction Ajouter un nouveau portefeuille Êtes-vous sûr de vouloir supprimer ce portefeuille ? Une erreur s\'est produite, veuillez scanner votre carte ou bague pour vous connecter @@ -1384,6 +1389,7 @@ Nous avons un problème. Toutes les dApps sont déconnectées Autoriser à dépenser + En approuvant, vous autorisez la dApp ou le contrat intelligent à utiliser les jetons dans de futures transactions. Adresse Connecter Chargement @@ -1451,4 +1457,82 @@ Non, envoyer toute la somme Réduire de %s XTZ Pour ne pas payer un fraid de commissions élevé la prochaine fois que vous rechargez votre portefeuille, veuillez réduire le montant de %s XTZ + Vos fonds sont actuellement fournis au protocole Aave, mais vous pouvez les gérer à tout moment. + Vos %s sont fournis à Aave. + Le transfert de %1$s %2$s vers Aave est en attente. + Donnez votre accord + Un problème est survenu lors de votre précédente approbation, nous avons donc besoin d\'une nouvelle approbation. Choisissez comment vous souhaitez procéder. + Autorisation nécessaire + Les frais seront prélevés et vos actifs seront à nouveau prêtés. + Pour continuer à percevoir des revenus, une autorisation est nécessaire. + Confirmer l\'approbation + Vos fonds sont actuellement affectés au protocole Aave, mais vous pouvez les gérer à tout moment. + Vos %s sont déposés dans Aave. + Impossible de charger le graphique... + Le montant reçu, %1$s %2$s, n\'a pas été fourni à Aave. + APY %1$s%% + Disponible + APY actuel + Lors du rechargement pour le dépôt, des frais de réseau ne dépassant pas %1$s seront déduits du solde. + Les frais de réseau sont actuellement trop élevés pour permettre l\'exécution des prêts. Les fonds seront versés dès qu\'ils auront baissé à %1$s ou moins. + Mes fonds + Vos %1$s sont désormais déposés chez Aave et rapportent des intérêts. Vous détenez %2$s tokens, ce qui représente votre solde et augmente au fil du temps. Lorsque vous déposez davantage de fonds, ceux-ci sont fournis à Aave afin de rapporter des intérêts, moins les frais de transaction. + Gagner + Total des gains + Transferts vers Aave + Découvrez Aave + Il s\'agit des frais d\'approvisionnement actuels sur %s. Le coût réel sera indiqué dans l\'onglet Activation. + Frais actuels + Tous les futurs dépôts %s seront automatiquement fournis à Aave, après déduction des frais de transaction. + Des frais de réseau d\'environ %1$s (%2$s) seront déduits de chaque recharge future, sans dépasser votre limite de %3$s (%4$s). + Si les frais de réseau dépassent le montant maximal, la transaction ne sera pas effectuée tant qu\'ils n\'auront pas diminué. Vous pouvez modifier cette limite ultérieurement. + Frais maximaux + Le montant minimum est calculé à partir des frais de réseau actuels afin de garantir qu\'il ne dépasse pas 4 %%, ce qui donne un minimum de %1$s (%2$s). + Recharge minimale + Politique tarifaire + Tangem prélève également des frais de service de 15% sur les revenus générés. + Vos fonds seront automatiquement transférés vers Aave dès que les frais de réseau seront moins élevés ou que votre solde atteindra le montant minimum requis. + Rendements historiques + L\'autorisation pour votre token en mode Yield a été révoquée. Ouvrez le token pour accorder à nouveau l\'autorisation. + Approbations de tokens nécessaires + Vérifiez votre connexion réseau. + Informations sur les frais de réseau inaccessibles + Chaque dépôt que vous effectuez sera automatiquement transféré à Aave. + Transfert automatique vers Aave + Envoyez, échangez ou vendez vos fonds instantanément, quand vous le souhaitez. + Accédez à vos fonds à tout moment + Comment ça marche ? + Aave est un protocole décentralisé qui gère plus de 61 milliards de dollars en valeur totale. + Décentralisé et auto-détenu + En utilisant ce service, vous acceptez les conditions générales du fournisseur %1$s et %2$s. + Connecter Aave + Aave %1$s%% • Taux d\'intérêt variable + Aave + Moyenne %s + Rendements de l\'année dernière + Le taux d\'intérêt actuel est toujours variable et calculé automatiquement par le contrat intelligent Aave, en fonction de l\'offre et de la demande en temps réel. + Alimenté par + Le taux d\'intérêt est variable. + Lorsque vous effectuez un dépôt, vos fonds sont automatiquement transférés vers Aave afin de commencer à générer des intérêts. %s sera déduit pour couvrir les frais de transaction. + Actifs d\'approvisionnement + Vos %s seront fournis à Aave, mais resteront gérables. + Voir la politique tarifaire + Vos prochains dépôts seront automatiquement transférés vers Aave. + Actif + En pause + Désactiver le mode rendement + En désactivant cela, vos fonds seront retirés d\'Aave vers %s dans votre portefeuille et vous ne gagnerez plus de récompenses. + Les frais de réseau seront déduits du montant que vous retirez. + Rendement annuel brut (APY) + APY + Les intérêts sont cumulés automatiquement. + Les intérêts sont cumulés automatiquement. + Mode de rendement + Traitement de votre dépôt + Mode Rendement + Automatique + Déposez %1$s %2$s pour couvrir les frais de réseau liés aux transactions. + Impossible de couvrir les frais %s + Le service d\'intérêt n\'est pas disponible pour le moment. Veuillez réessayer plus tard. + Gains indisponibles diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 97d1117305..2d8b7ca984 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -22,6 +22,9 @@ すでにアクティブアカウントの上限(20件)に達しています。復元するには、1つをアーカイブしてください。 アカウントを復元できません アーカイブ済み + アカウントをアーカイブできませんでした。しばらくしてからもう一度お試しください。 + このアカウントは紹介プログラムに参加しています。 + このアカウントはアーカイブできません。 アカウントを作成できませんでした。しばらくしてからもう一度お試しください。 アカウントを作成しました アカウントをアーカイブする @@ -29,6 +32,7 @@ このアカウントをアーカイブしますが、いつでも復元できます。 アカウント アカウントが保存されました + 報酬用のアカウント アカウント番号%s — アドレス導出に使用されます。 アカウントを追加 保存 @@ -40,6 +44,8 @@ アカウントを編集 %1$s ( %2$s内) メインアカウント + すでにアクティブアカウントの上限%1$s件を超えています。復元するには、1つをアーカイブしてください。 + アカウントを復元できません アカウントが回復しました アカウントを長押しして並べ替える 編集を続ける @@ -134,7 +140,7 @@ お使いの携帯電話で生体認証が無効になっているため、アプリにウォレットを保存できません。ウォレットを保存するには、携帯電話の設定で生体認証機能を有効にしてください。 プロモーションコードの処理中にエラーが発生しました。しばらくしてからもう一度お試しください。 アクティベーションエラー - プロモコードが正常に有効化されました。リワードは14日以内にあなたのアカウントに付与されます。 + プロモーションコードが正常に有効化されました。報酬は14日以内にビットコインアカウントに入金されます。 プロモーションコードが有効になりました このプロモーションコードは既に使用されているため、再度使うことはできません。 コードが利用できません @@ -175,11 +181,13 @@ ADAが不足しています。 受け入れる アクセスが拒否されました + アカウント アカウント 有効化 追加 ポートフォリオに追加 トークンを追加 + 追加済み アドレス すべて 許可する @@ -237,6 +245,7 @@ 有効にする 有効 エラー + ネットワークサービス手数料 スワップ 移動する 取引履歴を調べる @@ -248,10 +257,12 @@ 遅い 速度と料金 終了 + 忘れる 無料 送信元 アドレスを同期する はじめる + トークンを取得 プロバイダーへ移動 トークンへ移動 わかりました @@ -291,6 +302,7 @@ %1$s — %2$s 続きを読む 受け取る + おすすめ 拒否 リロード 名前を変更 @@ -347,6 +359,8 @@ はい コントラクトアドレスをコピーしました! 利用可能なネットワーク + このトークンの導出パスが%1$sの導出パスと一致しています。トークンはこのアカウントに追加されます。 + 導出パスは別のアカウントに属します。 コントラクトアドレス コントラクトアドレスが無効です ネットワークを選択してください @@ -464,6 +478,7 @@ プロバイダー ベストレート FCA警告リスト + ベストチョイス FCA警告リストに掲載されたプロバイダー 最大 %s まで使用可能 %s 以上で利用可能 @@ -499,7 +514,7 @@ エラーが発生しました。コード: %s 。 メモが必要 取引 - 選択したトークンの承認制限を指定します + 承認すると、このスマートコントラクトが今後の取引でトークンを利用できるようになります。 金額%s 承認機能は、別のアドレスに特定の量のトークンを使用する許可を与えるために必要です。設計上スマートコントラクトは、承認しない限りトークンにアクセスできません。トークンを「ロック解除」すると、StakeKitスマート コントラクトがトークンを使用する権限が与えられます。ネットワークのマイナーは、このアクションをブロックチェーンに記録するためにガス料金(あなたが支払う)を受け取ります。承認後、トークンをステーキングできます。 続行するには、Polygonスマートコントラクトが%sを使用することを許可する必要があります @@ -521,16 +536,23 @@ アクセスコードでアプリを保護して、設定を完了してください。 そうした場合は、最初からやり直す必要があります。 本当にアクティベーション処理を終了してもよろしいですか? + 暗号資産をオフラインで厳重保管。カードサイズで、金庫以上の安心を。 実行すると、最初からやり直す必要があります。 Googleドライブのバックアップから既存のウォレットを復元する Googleドライブのバックアップ + さらに強固なセキュリティのために、新しいウォレットを作成して資産を移動しましょう。 + 新しいウォレットを作成 Tangemの高性能ハードウェアウォレットで、セキュリティをさらに強化しましょう。 ハードウェアウォレット + 現在のウォレットをTangemウォレットに移します。 + 現在のウォレットをアップグレードする バックアップへ移動 アクセスコードを作成する前にウォレットをバックアップしてください。 まずバックアップを完了する + その他の方法 秘密鍵をオフラインで安全に保存する物理デバイス。 リカバリーフレーズ + ウォレットをハードウェアにアップグレードするには、まずバックアップしてください。 鍵はアプリに保存されます シードフレーズのバックアップ モバイルウォレットを作成する @@ -598,6 +620,7 @@ 選択したトークンは現在、暗号資産ウォレット内でのアクションには利用できません。しかし、心配しないでください。賛成票を投じることで関心を表明できます。 賛成票を投じる ウォレットは複数のネットワークをサポートしていません。 + コインについて このアセットを購入・交換・受け取るには、ポートフォリオに追加してください。 このアセットは現在ウォレットで利用できません このアセットはこのウォレットでは使用できません。 @@ -633,6 +656,7 @@ トレンド ステーキングは暗号資産で報酬を受け取る最も簡単な方法です。 %s 最大%s APYを獲得 + トークンを追加しました %sについて %d取引所 @@ -860,6 +884,7 @@ その他の通貨 人気の法定通貨 通貨で検索 + 最良のレートを取得しています... 即時 オンランプ機能を使用することにより、プロバイダの%1$sおよび%2$sに同意するものとします サービスは外部プロバイダーによって提供されます。 \nTangemは責任を負いません。 @@ -889,6 +914,7 @@ 最大%d日 %s分 + 利用可能: 以下が手に入ります。 サービスは外部プロバイダーによって提供されます。 \nTangemは責任を負いません。 この画面を閉じて、トークンの詳細画面で取引状況を確認できます。 @@ -951,6 +977,10 @@ このカードを使用して、現在のウォレットの他のカードのアクセスコードを回復させられないことを認識しています。 工場出荷時設定にリセットすると、選択したカードやリングからウォレットが完全に削除されます。現在のウォレットを復元したり、カードやリングを使用してアクセスコードを復元することはできません。 工場出荷時の状態にリセットすると、選択したカードやリングからウォレットが完全に削除され、アプリから削除されます。現在のウォレットを復元することはできません。 + すべてのTangemデバイスがリセットされました。 + アクティベーション処理中に問題が発生しました。カードを1枚ずつリセットしてください。 + カード認証に失敗しました + 続行するには次のデバイスをリセットしてください Tangem Ringユーザーは、11/15日までChangelly経由でスワップを3回手数料ゼロで行えます! 今すぐ手数料0% でスワップしましょう! アプリにログインして、カードまたはリングをスキャンせずに残高を確認できます @@ -1160,7 +1190,7 @@ 新しいバリデーターを使用して%1$sネットワークにステーキングすると、以前にステーキングされた資金がすべてこのバリデーターに自動的に転送されます。 獲得した報酬をステーキングに再投資し、潜在的な収益を増やします。 再ステーキングを使うと、ステーキングを解除することなく、あるバリデータから別のバリデータに資金を移動できます。 - 残高のすべてをステーキングしようとしています。ステーキング解除や報酬請求にかかるネットワーク手数料をカバーするために、少額を残しておくことをお勧めします。 + ウォレットの残高をすべてステーキングすると、ステーキング解除時にネットワーク手数料の支払いが必要になります。そのため、少額をウォレットに残しておくことをおすすめします。 ステーキングを始めるには、TONアカウントを1 TONの自己取引で有効化する必要があります。資金はウォレット内にそのまま残り、この手順でステーキング用にアカウントを有効化できます。 アカウントの有効化 TONのステーキングを開始するには、まず自分のアドレスに少額の取引を送信します。これによりウォレットが有効になります。 @@ -1195,7 +1225,7 @@ 毎月 毎週 報酬 - Solanaの報酬は自動的にステーキング残高に追加され、個別に表示することはできません。 + Solanaの報酬は自動的にステーキング残高に追加され、個別に表示することはできません。 ステーキングはロックされています もっとステーキングする %1$sをステーキングすると、 %2$s残高全体がステーキングされます。Tangemウォレットに入金した追加の%2$sも、自動的にステーキングされます。 @@ -1268,8 +1298,25 @@ 受け取る トークンを選択 利用不可 + 入金 + 異議申し立て + 取引を表示 + サービス手数料 + 手数料 + 完了 + 拒否 + 保留中 + 銀行がこの取引リクエストを拒否しました。 + この手数料は、送金処理にかかるコストをカバーするためのものです。 + 出金 + PINを変更する + カードは支払いの準備が整いました。 + PINコードを作成しました データの読み込みに失敗しました。しばらくしてからもう一度お試しください。 + カードの一時停止 非表示 + 技術的な問題が検出されました。しばらくしてからもう一度お試しいただくか、サポートにお問い合わせください。 + 現在、受け取りは利用できません 表示 カードの詳細 アカウントを作成してカードを発行 @@ -1301,6 +1348,7 @@ ネットワーク%s内の保留中の取引が完了すると、送金が可能になります。 %sの売却は、現在のプロバイダーではサポートされていませんが、より多くのオプションを追加できるよう取り組んでいます。 %sのステーキングは、現在のプロバイダーではサポートされていませんが、より多くのオプションを追加できるよう取り組んでいます。 + 承認が取り消されましたが、あなたの資金は引き続き利息モードです。操作を行うには、利息モードに移動し、再度承認を付与してください。 XPUBを生成する 非表示 このトークンをメイン画面から非表示にします。トークンの管理ページからいつでも再度追加できます。 @@ -1361,9 +1409,10 @@ 新しい機能や限定オファーへの早期アクセス。 機能およびニュースのアップデート プッシュ通知を使用しますか? - プッシュ通知を有効にすると、資金が到着するとすぐに通知されます + プッシュ通知を有効にすると、ウォレットに着金したときにアラートを受信できます。 取引を見逃さない 新しいウォレットを追加 + バックアップせずにこのウォレットを削除すると、資金に永久にアクセスできなくなります。 このウォレットを忘れてもよろしいですか? エラーが発生しました。カードまたはリングをスキャンしてログインしてください。 このウォレットはすでに保存されています。別のウォレットを追加できます。 @@ -1393,6 +1442,13 @@ ロック解除 カードをスキャンしてアクセスロックを解除する ロック解除が必要 + ウォレットの追加方法を選択してください + Tangemカードまたはリングをスキャンして復元するか、別のウォレットからインポートしてください。 + ハードウェアウォレットを作成 + Tangemウォレットを購入しますか? + シードフレーズをインポート + スマートフォン上でウォレットを復元するか、他のアプリからインポートできますが、Tangemカードと比べるとセキュリティは劣ります。 + お選びください ブロックチェーンにアクセスできません。後でもう一度お試しください。 カードまたはリングをスキャン このウォレットはすでに有効化されています。\nあなたが行ったのでない場合は、サポートに連絡してください。\nTangemは、事前に生成されたアクセスコードと一緒にウォレットを販売することはありません。 @@ -1432,6 +1488,7 @@ dAppsに接続する WalletConnect 接続には数秒かかる場合があります + Tangemウォレットを作成する %sから Tangemウォレットを購入ーこれは、あなたの秘密鍵をオフラインで安全に保管する物理デバイスです。 ハードウェアウォレット @@ -1657,13 +1714,20 @@ URIはすでに使用されています WalletConnect 不審な取引 + すでにTangemをお持ちですか? + 数千種類の資産 業界最高水準のハードウェアウォレット 迅速な配送 + ワンタップで開始 + シームレスで安全 シンプルな操作 Tangemでハードウェアウォレットを作成しましょう。銀行のカードのようにスリムで、金庫のように安全です。 ソフトウェアウォレットを作成またはインポート + スマートフォン上にソフトウェアウォレットを作成するか、インポートしてください。 モバイルウォレットから始める その他の方法 + Tangemハードウェアウォレットを使用する + 詳細を見る・購入する 破棄 バックアップが中断されました。再開しますか? はい、再開します @@ -1678,75 +1742,84 @@ いいえ、すべて送信します %s XTZを減らす 次回ウォレットにチャージするときに手数料の増加を避けるには、金額を%s XTZ減らしてください。 - 資産残高に関するテキスト [プレースホルダー] - %sはAaveに預け入れられています + 利息モードを有効にすると、このアドレスへの今後のすべての入金はAaveに送られます。ただし、資金の管理は引き続き自由に行えます。 + %sはAaveに供給されています + Aaveへの%1$s %2$sの供給は保留中です 承認する - 前回の承認に問題があったため、新しい承認が必要です。手続き方法を選択してください。 + トークンの承認は取り消されました。サービス機能を再開するには、再度承認を行ってください。 承認が必要 手数料が差し引かれ、あなたの資産は再び貸し出されます。 引き続き収益を得るには承認が必要です。 承認を確定する - 資産残高に関するテキスト [プレースホルダー] + あなたの資金は現在Aaveプロトコルに預けられていますが、いつでも自由に管理できます。 あなたの%sはAaveに預けられています チャートを読み込めません・・ 受け取った金額%1$s %2$sはAaveに入金されませんでした。 - %1$s%% を獲得 + 年利%1$s%% 利用可能 現在のAPY + 貸付のために入金する際は、残高から%1$s以下のネットワーク手数料が差し引かれます。 + 現在、ネットワーク手数料が高すぎるため貸付を実行できません。手数料が%1$s以下に下がり次第、資金が供給されます。 私の資金 - あなたの%1$sはAaveに預けられ、利息が付きます。あなたは%2$sトークンを保有しており、これは残高を表し、時間の経過とともに増加します。入金すると、資金はAaveに預け入れられ、取引手数料を差し引いた利息が付きます。 - 利回りを得る + あなたの%1$sは現在Aaveにデプロイされ、利回りを生んでいます。あなたは%2$sトークンを保有しており、これはあなたの残高を表し、自動的に利回りが発生します。追加入金すると、手数料を差し引いた上でAaveに資産が追加され、さらに利回りを得られるようになります。 + 利息モード 総収益 Aaveへの送金 Aaveの詳細を見る - これは%sの現在の供給手数料です。実際のコストは受取画面に表示されます。 + これは%sの現在の供給手数料です。実際のコストはアクティベーションタブに表示されます。 現在の手数料 今後の%sの入金はすべて、取引手数料が差し引かれて自動的にAaveに供給されます。 + 今後のチャージごとに、おおよそ%1$s(%2$s)のネットワーク手数料が差し引かれますが、上限の%3$s(%4$s)を超えることはありません。 ネットワーク手数料が上限手数料を超えた場合、手数料が下がるまで取引は成立しません。この制限は後で変更できます。 最大手数料 + 最小金額は現在のネットワーク手数料に基づいて計算されており、手数料が4%を超えないように設定されています。そのため、最小金額は%1$s(%2$s)となります。 + 最低入金額 手数料ポリシー - ネットワーク手数料が現在高すぎます。設定した上限を下回るまで待機しています。 + Tangemはまた、得られた利回りに対して15%のサービス手数料を差し引きます。 + ネットワーク手数料が下がるか、残高が最低必要額に達すると、資金は自動的にAaveに供給されます。 過去のリターン - ここに説明を入力してください。1〜3行が理想的です。[プレースホルダー] - トークン承認が必要 + 利息モードでのトークンの承認が取り消されました。トークンを開いて再度許可してください。 + トークンの承認が必要です ネットワーク接続を確認してください ネットワーク手数料についての情報にアクセスできません - アカウントへの入金はすべて自動的にAaveに貸し出されます。 - 残高は自動的に計算されます + あなたが行うすべての入金は、自動的にAaveへ供給されます。 + Aaveへの自動送金 いつでも、即座に資金を送信、交換、売却できます。 - すぐに現金化 + いつでも資金にアクセス可能 使い方 - Aaveは世界中で何百万人もの人々に信頼されています。総貸付額は104億ドルです。 + Aaveは、総額610億ドル以上の資産を管理する分散型プロトコルです。 分散型・自己管理型 - サービスを利用することにより、プロバイダー\n %1$sおよび%2$sに同意したことになります - 年間%s%%の収益 - Aave • 変動金利 + このサービスを利用することにより、プロバイダー\n%1$sおよび%2$sに同意するものとします。 + Aave を接続 + Aave %1$s%% • 変動金利 Aave 平均%s 昨年のリターン - 現在の金利は常に変動し、リアルタイムの需要と供給に基づいて、AAVEオンチェーンスマートコントラクトによって自動的に計算されます。 + 現在の金利は常に変動し、リアルタイムの需要と供給に基づいて、Aaveオンチェーンスマートコントラクトによって自動的に計算されます。 提供 金利は変動します - 入金すると、資金は自動的にAaveに送金され、利息が付き始めます。取引手数料として%s相当の少額の手数料が差し引かれます。 - 利息の獲得を開始 - %sはAaveに供給され、すぐに利用可能になります + 入金すると、資金は自動的にAaveに送金され、利息が付き始めます。%sが取引手数料として差し引かれます。 + 資産を供給する + %sはAaveに供給されますが、管理可能な状態のままになります。 手数料ポリシーを見る 次回の入金は自動的にAaveに供給されます。 アクティブ 停止中 - 収益を停止する - オフにすると、Aaveから資金が引き出され、ウォレットの%sに戻され、報酬の獲得が停止されます。 + 利回りモードを無効にする + これをオフにすると、Aaveから資産が引き出され、ウォレット内の%sに変換され、利回りの発生が停止します。 出金金額からネットワーク手数料が差し引かれます。 - 供給APR + 供給 + 供給APY APY - あなたの資産を眠らせない — 残高を運用して利息を得ましょう。 - 保有資産から報酬を得る + 利息は自動的に発生します + 利息は自動的に発生します + 利回りモード 入金の処理中 - 年間%1$s%%の収益 + 利息モード 自動 取引のネットワーク手数料をカバーするために、 %1$s %2$sを入金してください %s手数料を支払えません - 利息サービスは現在利用できません。しばらくしてから再度お試しください。 - 収益は利用できません + 現在、利息モードのサービスは利用できません。しばらくしてから再度お試しください。 + 利息モードは利用できません チャートを読み込めません・・ diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 6d0accb1ee..393f0891ea 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -80,7 +80,7 @@ Вы отключили биометрическую аутентификацию на вашем телефоне и не сможете сохранять кошельки в приложении. Для сохранения кошельков, пожалуйста, включите функцию биометрической аутентификации в настройках телефона. При обработке промокода произошла ошибка. Пожалуйста, попробуйте позже. Ошибка активации - Ваш промокод был успешно активирован. Награда будет зачислена на ваш счёт в течение 14 дней. + Ваш промокод был успешно активирован. Награда будет зачислена на ваш Bitcoin адрес в течение 14 дней. Промокод активирован Этот промокод уже был использован и не может быть активирован повторно. Код недоступен @@ -181,6 +181,7 @@ Включить Включено Ошибка + Комиссия сети Обменять Обозреватель Посмотреть историю транзакций @@ -192,8 +193,10 @@ Медленно Скорость и комиссия Завершить + Забыть Из Синхронизировать адреса + Начать зарабатывать К провайдеру Перейти в токен Понятно @@ -202,6 +205,7 @@ Импортировать В процессе Позже + Узнать больше Осталось %1$s Заблокирован Основная сеть @@ -392,6 +396,7 @@ Больше провайдеров на подходе.\nСледите за обновлениями! Провайдер Лучший курс + Лучший выбор Доступно до %s Доступно с %s Недоступно для этой пары @@ -526,6 +531,7 @@ Выбранный токен не доступен в кошельке на данный момент. Но не переживайте, вы можете выразить свой интерес проголосовав за его добавление. Голосовать Кошелёк не поддерживает более одной сети + О монете Чтобы купить, обменять или получить данный токен, вам нужно добавить его к себе в портфель Этот актив в настоящее время не поддерживается в кошельке Этот токен не доступен для данного кошелька @@ -560,6 +566,7 @@ В тренде Стейкинг — простой способ получать доход с вашей криптовалюты. %s Получайте до %s APY + Токен добавлен О %s %d биржа @@ -694,6 +701,8 @@ Купить криптовалюту Наслаждайтесь **нулевой комиссией** при покупке криптовалюты через SEPA-переводы. Покупайте крипту через SEPA + Присоединяйтесь к списку ожидания и получите уникальную платёжную карту, не похожую ни на одну другую. + Tangem Visa Card Установите единый код доступа для защиты всех ваших карт или колец Защита Установите индивидуальный код доступа для каждой карты или кольца позже. @@ -837,6 +846,7 @@ до %d дней %s мин + Доступно от Вы получите Вы можете закрыть этот экран и проверить статус транзакции на экране информации о токене. До @@ -1141,7 +1151,7 @@ Месяц Еженедельно Вознаграждения - Вознаграждения в сети Solana автоматически добавляются к вашему стейкинг-балансу и не могут отображаться отдельно. + Вознаграждения в сети Solana автоматически добавляются к вашему стейкинг-балансу и не могут отображаться отдельно. Стейкинг закрыт Застейкать еще При стейкинге %1$s используется весь ваш баланс в %2$s. Любой дополнительный %2$s депозит будет автоматически застейкан. @@ -1213,6 +1223,7 @@ Вы получите Выберите токен не доступен + Комиссия Это мой кошелек Балансы скрыты Балансы показаны @@ -1229,6 +1240,7 @@ Отправка средств станет доступной после завершения транзакции(-ий) в сети %s Продажа %s в данный момент не поддерживается ни одним провайдером. Мы работаем над добавлением новых возможностей. Следите за нашими новостями. Стейкинг %s в данный момент не поддерживается ни одним провайдером. Мы работаем над добавлением новых возможностей. Следите за нашими новостями. + Разрешение было отозвано. Ваши средства остаются в Yield сервисе. Чтобы совершать операции, перейдите в Yield сервис и снова выдайте разрешение. Сгенерировать XPUB Скрыть Вы скрываете токен с главного экрана, но в любой момент сможете добавить его обратно через страницу управления токенами. @@ -1288,6 +1300,8 @@ Ранний доступ к новым функциям и эксклюзивным предложениям. Новые функции и важные новости Хотите использовать Push-уведомления? + Включите push-уведомления, и мы мгновенно сообщим вам, когда поступят средства. + Не пропустите транзакцию Добавить новый кошелек Вы уверены, что хотите забыть этот кошелек? Произошла ошибка, пожалуйста, отсканируйте свою карту или кольцо для входа @@ -1485,6 +1499,7 @@ Похоже, возникла проблема Все dapps отключены Разрешение на использование + Подтверждая, вы разрешаете смарт-контракту использовать ваши токены в будущих транзакциях. Адрес Подключение Загрузка @@ -1545,6 +1560,7 @@ URI уже используется WalletConnect Подозрительная транзакция + Узнать больше и купить Отказаться Вы не закончили резервное копирование. Хотите продолжить? Да, возобновить @@ -1559,14 +1575,76 @@ Нет, отправить все Уменьшить на %s XTZ Чтобы не платить повышенную комиссию при следующем пополнении кошелька, уменьшите сумму на %s XTZ + При активном режиме доходности все будущие депозиты на этот адрес будут направляться в Aave. Вы по-прежнему можете свободно управлять своими средствами. + Ваш %s внесён в Aave Выдать разрешение + Разрешение для вашего токена было отозвано. Выдайте его снова, чтобы продолжить работу сервиса. + Необходимо разрешение + Комиссия будет списана, и ваши активы снова начнут приносить доход. + Чтобы продолжить зарабатывать, нужно выдать разрешение. + Подтвердить разрешение + Ваши средства в данный момент размещены в протоколе Aave, но вы можете воспользоваться ими в любое время. + Ваш %s внесён в Aave Невозможно загрузить график Полученная сумма, %1$s %2$s, не была зачислена на Aave. - Сетевая комиссия сейчас слишком высокая. Ожидаем, пока она упадёт ниже вашего лимита. + APY %1$s%% + Доступно + Текущий APY + Мои средства + Ваши %1$s теперь внесён в Aave и приносит проценты. У вас есть токен %2$s, который отражает ваш баланс и со временем увеличивается. При пополнении средства автоматически направляются в Aave для получения процентов за вычетом комиссии за транзакцию. + Итоговый доход + Переводы в Aave + Изучите Aave + Это текущая комиссия в сети %s. + Текущая комиссия + Все следующие пополнения %s автоматически поступят в Aave с удержанием комиссии за транзакцию. + Если комиссия сети превысит максимальный лимит, транзакция не будет выполнена до тех пор, пока комиссия не снизится. Вы сможете изменить этот лимит позже. + Максимальная комиссия + Это минимальный депозит, который можно отправить в Aave. Чтобы депозиты оставались прибыльными, мы не обрабатываем их, когда комиссия сети превышает %1$s%2$sот суммы. + Минимальный депозит + Политика комиссий + Tangem взимает комиссию за обслуживание в размере 15% от полученного дохода. + Ваши средства будут автоматически переведены в Aave, как только комиссия сети снизится или баланс достигнет минимально необходимой суммы. Историческая доходность + Разрешение для вашего токена в Yield сервисе было отозвано. Откройте токен, чтобы выдать разрешение снова. + Необходимо разрешение для токена Проверьте ваше интернет соединение - Годовая доходность - Сервис начисления процентов в данный момент недоступен. Пожалуйста, попробуйте позже. - Данные о доходе недоступны + Информация о комиссии недоступна + Каждое пополнение вашего адреса автоматически будет отправляться в Aave. + Автоперевод в AAVE + Отправляйте, обменивайте или продавайте свои средства мгновенно, когда захотите. + Мгновенный вывод средств + Как это работает? + Aave — это децентрализованный протокол, управляющий активами на сумму более 61 миллиарда долларов США. + Децентрализованный и некастодиальный + Используя сервис, вы соглашаетесь с условиями провайдера %1$s и %2$s + Подключить Aave + Aave %1$s%%• Ставка с плавающим процентом + Aave + Сред. %s + Доходность за прошлый год + Текущая процентная ставка всегда переменная и автоматически рассчитывается смарт-контрактом AAVE в блокчейне на основе текущего спроса и предложения. + При поддержке + Ставка может меняться + При пополнении ваши средства автоматически отправляются в Aave для начала начисления процентов. Для покрытия комиссии с вас будет удержана небольшая плата в размере %s. + Начать зарабатывать + Ваш %s будет передан в Aave и останется всегда доступным. + Политика комиссий + Следующие пополнения вашего счёта автоматически поступят в Aave. + Активен + На паузе + Завершить заработок + Выключив эту функцию, вы выведёте средства из Aave, получите их обратно в %s в своем кошельке и перестанете зарабатывать награды. + Комиссия сети будет вычтена из суммы вашего вывода. + Годовая доходность (APY) + APY + Проценты начисляются автоматически. + Режим доходности + Отправка ваших средств + Автоматически + Внесите немного %1$s %2$s, чтобы покрыть комиссию сети за транзакции. + Невозможно покрыть комиссию в %s + Сервис доходности в данный момент недоступен. Пожалуйста, попробуйте позже. + Режим доходности недоступен Невозможно загрузить график diff --git a/core/res/src/main/res/values-uk-rUA/strings.xml b/core/res/src/main/res/values-uk-rUA/strings.xml index 4e66cabc58..936f193cce 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -629,6 +629,8 @@ Купити криптовалюту Насолоджуйтесь **нульовою комісією** при купівлі криптовалюти через перекази SEPA. Купуйте криптовалюту через SEPA + Приєднуйтесь до списку очікування та отримайте унікальну платіжну картку, якої ще не було. + Tangem Visa Card Налаштуйте єдиний код доступу для захисту всіх ваших карток або кілець Захист Встановіть індивідуальний код доступу для кожної картки або кільця пізніше. @@ -1086,6 +1088,7 @@ Web 3.0 сумісність Для відправки потрібна вхідна транзакція на суму не менше %1$s Недостатньо коштів + Підтверджуючи, ви дозволяєте смартконтракту використовувати ваші токени в майбутніх транзакціях. Мережа стягує комісію за схвалення токену за підтвердження, що саме ви дозволяєте використовувати ваш токен для обміну. Обмінюйте більше токенів за вигіднішим курсом прямо у своєму гаманці. З\'явився новий провайдер обмінів! @@ -1366,6 +1369,7 @@ Обрана не вірна картка або кільце Схоже, виникла проблема Усі dApps відключені + Підтверджуючи, ви дозволяєте dApp або смартконтракту використовувати токени в майбутніх транзакціях. Адреса Підключення Мережа @@ -1430,4 +1434,80 @@ Ні, відправити все Зменшити на %s XTZ Щоб не платити підвищену комісію при наступному поповненні гаманця, зменште суму на %s XTZ + З активним режимом дохідності всі майбутні депозити на цю адресу будуть надходити до Aave. Ви все ще можете вільно розпоряджатися своїми коштами. + Ваш %s внесений до Aave + Передача %1$s %2$s до Aave очікується + Дати згоду + Схвалення для вашого токена було відкликано. Надайте його знову, щоб відновити роботу сервісу. + Потрібне схвалення + Комісія буде знята, а ваші активи знову почнуть приносити дохід. + Щоб продовжити заробляти, потрібне схвалення. + Підтвердити дозвіл + Наразі ваші кошти розміщені у протоколі Aave, але ви можете керувати ними в будь-який час. + Ваш %s внесений у Aave + Неможливо завантажити графік + Отримана сума, %1$s %2$s не була зарахована на Aave. + APY %1$s%% + Доступно + Поточний APY + При поповненні для кредитування з балансу буде вирахувано комісію мережі, що не перевищує %1$s. + Наразі мережева комісія є занадто високою, щоб здійснювати кредитування. Кошти будуть надані, як тільки вона знизиться до %1$s або нижче. + Мої кошти + Ваші %1$s тепер розміщено в Aave і приносить дохід. У вас є токен %2$s, який представляє ваш баланс і з часом збільшується. При поповненні кошти автоматично направляються в Aave для отримання процентів з вирахуванням комісії за транзакцію. + Режим дохідності + Підсумковий дохід + Перекази в Aave + Дослідити Aave + Це поточна комісія у мережі %s. + Поточна комісія + Усі майбутні депозити %s будуть надходити до Aave автоматично, з вирахуванням комісії за транзакцію. + Приблизна мережева плата в розмірі %1$s (%2$s) буде вираховуватися з кожного наступного поповнення, і вона не перевищуватиме ваш ліміт %3$s (%4$s). + Якщо мережеві комісії перевищують максимальну комісію, транзакція не пройде, поки вони не знизяться. Ви можете змінити цей ліміт пізніше. + Максимальна комісія + Це найменший депозит, який можна надіслати в Aave. Щоб депозити залишалися прибутковими, ми не обробляємо їх, коли комісія мережі перевищує %1$s%2$s від суми. + Мінімальне поповнення + Політика комісій + Tangem комісію за обслуговування у розмірі 15% від отриманого доходу. + Ваші кошти будуть автоматично переведені у Aave, як тільки мережеві комісії знизяться або ваш баланс досягне мінімально необхідної суми. + Історична прибутковість + Дозвіл для вашого токена в режимі Yield було відкликано. Відкрийте токен, щоб надати дозвіл знову. + Потрібний дозвіл для токену + Перевірте підключення до мережі + Інформація про комісію недоступна + Кожен ваш депозит буде автоматично надходити до Aave. + Автопереказ до AAVE + Відправляйте, обмінюйте або продавайте свої кошти миттєво, в будь-який час. + Миттєвий вивід коштів + Як це працює? + Aave — це децентралізований протокол, який управляє активами загальною вартістю понад 61 мільярд доларів. + Децентралізований та некастодіальний + Використовуючи сервіс, ви погоджуєтесь з умовами провайдера %1$s та %2$s + Підключити Aave + Aave %1$s%% • Ставка з плаваючим відсотком + Аave + Серед. %s + Дохідність за минулий рік + Поточна відсоткова ставка завжди змінна і автоматично розраховується смарт-контрактом Aave у блокчейні на основі попиту та пропозиції в режимі реального часу. + При підтримці + Ставка може змінюватися + Коли ви поповнюєте рахунок, ваші кошти автоматично надсилатимуться на Aave, щоб почати нараховувати відсотки. Для покриття комісії з вас буде утримана невелика плата у розмірі %s. + Почати заробляти + Ваш %s буде передано до Aave, і залишиться завжди доступним. + Політика комісій + Ваші наступні поповнення рахунку автоматично надходитимуть до Aave. + Активний + На паузі + Завершити заробіток + Вимкнення цієї опції виведе ваші активи з Aave, отримаєте їх назад у %s у вашому гаманці і зупинить накопичення нагород. + Комісія мережі буде вирахувана з суми, яку ви знімаєте. + Річна прибутковість (APY) + APY + Відсотки нараховуються автоматично + Режим дохідності + Відправка ваших коштів + Автоматично + Внесіть трохи %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 a6650d1da4..8b5e486e5f 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -22,13 +22,18 @@ You have already exceeded the limit of 20 active accounts. Archive one to recover. Can\'t recover account Archived + We couldn’t archive account. Please try again later. + This account participates in the referral program. + This account cannot be archived. We couldn’t create account. Please try again later. Account created Archive account Archive You are archiving this account, but you can always get it back. + Archiving... Account Account saved + Account for rewards Account #%s — used for address derivation. Add account Save @@ -40,6 +45,8 @@ Edit account %1$s in %2$s Main account + You have already exceeded the limit of %1$s active accounts. Archive one to recover + Can’t recover account Account recovered Long tap on an account to reorder accounts Keep Editing @@ -135,7 +142,7 @@ You have disabled biometric authentication on your phone and will not be able to save wallets in the app. To save wallets, please enable the biometric authentication function in your phone settings. An error occurred while processing your promo code. Please try again later. Activation error - Your promo code was successfully activated. A reward will be credited to your account within 14 days. + Your promo code was successfully activated. The reward will be credited to your Bitcoin account within 14 days. Promo Code Activated This promo code has already been used and cannot be activated again. Code unavailable @@ -178,11 +185,13 @@ Not enough ADA Accept Access denied + Account Accounts Activate Add Add to portfolio Add token + Added Address All Allow @@ -242,6 +251,7 @@ Enable Enabled Error + Network service fee Swap Explore Explore transaction history @@ -253,10 +263,12 @@ Slow Speed and fee Finish + Forget Free From Synchronize addresses Get started + Get token Go to provider Go to token Got it @@ -265,7 +277,7 @@ Import In progress Later - Learn more + Learn more %1$s left Legacy Bitcoin Locked @@ -297,6 +309,7 @@ %1$s — %2$s Read more Receive + Recommended Reject Reload Rename @@ -419,6 +432,7 @@ WalletConnect error You have used a card or ring from another wallet. Tap the card or ring associated with this wallet Not enough funds for the transaction. Please top up your account. + Swap any asset in your portfolio for this token My tokens You haven\'t added any tokens yet. Add tokens via Market to swap Cannot be swapped for %s @@ -474,6 +488,7 @@ Provider Best rate FCA Warning List + Best choice Provider in FCA warning list Available up to %s Available from %s @@ -509,7 +524,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 @@ -531,17 +546,24 @@ Complete setup by securing the app with an access code. If you do, you\'ll need to start over. Are you sure you want to quit the activation process? + Keeps your crypto safe and offline. Slim as a credit card, safer than a bank vault. If you do, you\'ll need to start over. Recover existing wallet via Google Drive backup Google Drive backup + Create a new secure wallet and transfer your funds for extra protection. + Create new wallet Level up your security with the superior Tangem hardware wallet. Hardware Wallet + Move your current wallet into Tangem Wallet. + Upgrade current wallet Go to backup Please back up your wallet before creating an access code. Finalize backup first Incomplete + Other methods Physical devices that securely store your private key offline. Recovery phrase + To upgrade your wallet to hardware, back it up first. Your private keys are securely encrypted and stored on your phone Keys are stored in the app Create or restore your wallet using a recovery phrase — your built-in backup. @@ -612,6 +634,7 @@ The selected token is currently unavailable for actions within the crypto wallet. But worry not, you can express your interest by upvoting it. Upvote The wallet doesn\'t support more than one network + About coin To buy, exchange, or receive this asset, add it to your portfolio This asset is currently not supported in the wallet This asset is not available for this wallet @@ -647,6 +670,7 @@ Trending Staking is the easiest way to receive rewards on your crypto. %s Earn up to %s APY + Token Added About %s %d exchange @@ -773,6 +797,8 @@ Buy crypto Enjoy **0% fees** when purchasing crypto via SEPA transfers. Buy Crypto with SEPA + Join the waitlist and get a payment card unlike any other + Tangem Visa Card Set up a single access code to protect all your devices. Protect Set an individual access code for each card or ring later. @@ -880,6 +906,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. @@ -911,6 +938,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. @@ -975,6 +1003,10 @@ I realize that I can\'t use this card to recover my access code on the other cards of the current wallet Factory Reset will completely delete the wallet from the selected card or ring. You will not be able to restore the current wallet or use the card or ring to recover the access code. Factory Reset will completely delete the wallet from the selected card or ring and remove it from the app. You will not be able to restore the current wallet. + All Tangem devices have been reset. + Something went wrong with the activation process. Please reset the cards one by one. + Card verification failed + Please reset the next device to continue Ring owners get 3 commission-free swaps on Changelly until 15.11! Swap With 0% Fees Now! Log into the app and check your balance without scanning the card or ring @@ -1185,7 +1217,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. @@ -1220,7 +1252,7 @@ Monthly Weekly Rewards - Rewards on Solana are automatically added to your staking balance and cannot be shown separately. + Rewards on Solana are automatically added to your staking balance and cannot be shown separately. Stake locked Stake more When staking %1$s, your entire %2$s balance is staked. Any additional %2$s you deposit to your Tangem Wallet will also be automatically staked. @@ -1293,8 +1325,34 @@ You receive Choose token not available + Deposit + Dispute + Explore transaction + Service fees + Fee + Completed + Declined + Pending + The bank rejected this transaction request. + This fee goes to cover the cost of handling your transfer. + Withdrawal + Change PIN + The card is fully ready for payments. + PIN code created Failed to load data. Try again later. + Freeze Card Hide + Open Google Wallet + Set up Tangem Pay in a few taps and start paying with Google Pay. + Add your card to Google Pay + Open Google Wallet + Tap “Add a card” + Enter the card details manually + Verify card using the OTP sent to your device. + All set! Your card is ready to use. + Add card to Google Pay + Technical issues detected. Please try again later or contact support. + Receive unavailable now Reveal Card details Create account and issue a card @@ -1326,6 +1384,7 @@ Sending funds will be available once the pending transaction(s) in network %s is complete Selling %s is not supported by current providers, but we are working to add more options. Staking %s is not supported by current providers, but we are working to add more options. + Approval has been revoked. Your funds remain in Yield mode. To perform actions, please go to Yield mode and grant permission again. Generate XPUB Hide You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. @@ -1386,9 +1445,10 @@ Early access to fresh features and exclusive offers. Feature and News Updates Would you like to use\nPush-notifications? - Enable push notifications and we’ll notify you instantly when funds arrive\n - Don’t Miss a Transaction + Enable push notifications to receive alerts when funds arrive in your wallet. + Don\'t Miss a Transaction Add new wallet + If you delete this wallet without a backup, you will permanently lose access to your funds Are you sure you want to forget this wallet? An error has occurred, please scan your card or ring to log in This wallet has already been saved, you can add another one @@ -1465,6 +1525,13 @@ Unlock Scan your card to unlock access Needed unlock + Choose how to add your wallet + Scan your Tangem card or ring to restore it or import from another wallet. + Create Hardware Wallet + Want to purchase a Tangem Wallet? + Import seed phrase + Restore your wallet on your phone or import from another app — convenient, but less secure than a Tangem card. + What to choose? Blockchain is unreachable. Try later Scan card or ring This wallet has already been activated earlier.\nIf it was not done by you, please contact support.\nTangem never sells wallets along with pre-generated access codes. @@ -1504,6 +1571,7 @@ Connect to dApps WalletConnect Connecting may take a few seconds + Create Tangem Wallet From %s Buy Tangem Wallet—a physical device that securely stores your private key offline. Hardware Wallet @@ -1759,76 +1827,84 @@ No, send all 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 + With Yield mode active, all future deposits to this address will go to Aave. You can still manage your funds freely. + Your %s is supplied to Aave + Supplying %1$s %2$s to Aave is pending Give Approve - Something went wrong with your previous approval, so we need a new one. Choose how you’d like to proceed. + Your token’s approval has been revoked. Grant it again to resume service functionality. Approve needed The fee will be taken out, and your assets will be lent again. To continue earning, approval is required. Confirm approval - Text about your money in balance [PLACEHOLDER] + Your funds are currently supplied to the Aave protocol, but you can manage them at any time. 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%% + The amount received, %1$s %2$s was not supplied to Aave. + APY %1$s%% Available Current APY - 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 + When topping up for lending, a network fee not exceeding %1$s will be deducted from the balance. + The network fee is currently too high to execute lending. Funds will be supplied once it drops to %1$s or below. + My funds + Your %1$s is now deployed to Aave and earning yield. You hold %2$s tokens, which represent your balance and accrue yield automatically. When you top up, funds are added to Aave to earn more yield, minus fees. + Yield mode Total earnings Transfers to Aave Explore Aave - Your %s is deposited in Aave - This is the current supply fee on %s. The live cost will be shown on the Receive Screen. + This is the current supply fee on %s. The actual cost will be shown on the activation tab. Current fee - All future %s top-ups will be supplied to Aave automatically, with the transaction fee deducted. + All future %s deposits will be supplied to Aave automatically, with the transaction fee deducted. + An approximate network fee of %1$s (%2$s) will be deducted from each future top-up, and it won’t exceed your %3$s (%4$s) limit. 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 minimum amount is calculated from the current network fee to ensure it does not exceed 4%%, which makes the minimum %1$s (%2$s). + Minimum top-up Fee policy - Network fee is too high right now. Waiting until it falls below your limit. + Tangem also takes a 15% service fee on yield earned. + Your funds will be automatically supplied to Aave once network fees are lower or your balance meets the minimum required amount. Historical returns - Write description here. In one, two or three lines will be awesome. [PLACEHOLDER] - Some token approve needed + Approval for your token in the Yield mode has been revoked. Open the token to grant permission again. + Token approval needed Check your network connection Network fee info unreachable - Every top-up of your account will be lended to Aave automatically. - Your balance works automatically + Every deposit you make will be supplied to Aave automatically. + Auto-Transfer to Aave Send, swap, or sell your funds instantly, anytime you want. - Cash out instantly + Access your funds anytime How it works? - Aave is trusted by millions worldwide. Total lended value is $10.4B. + Aave is a decentralized protocol managing over $61 billion in total value. Decentralized and self-custodial - By using service, you agree with provider\n%1$s and %2$s - Earn %s%% yearly - Aave • Variable Interest Rate + By using this service, you agree with provider\n%1$s and %2$s + Connect Aave + Aave %1$s%% • Variable Interest Rate Aave Avg %s - Last year returns - Current interest rate is always variable and automatically computed by AAVE on-chain smart-contract based on real-time supply and demand. + Last year\'s returns + Current interest rate is always variable and automatically computed by the Aave on-chain smart-contract, based on real-time supply and demand. 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 - Your %s will be supplied to Aave and will stay instantly available + When you top up, your funds will be automatically sent to Aave to start earning interest. %s will be deducted to cover the transaction fee. + Supply assets + Your %s will be supplied to Aave, but will remain manageable. 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. + Disable yield mode + Turning this off will withdraw your assets from Aave, convert them back to %s in your wallet, and stop yield accrual. The network fee will be deducted from the amount you withdraw. - Supply APR + Supply + Supply APY APY - Make your money work — earn interest on your balance. - Earning on your balance + Interest accrues automatically + Interest accrues automatically + Yield mode Processing your deposit - Earn %1$s%% per year + Yield Mode Automatic Deposit some %1$s %2$s to cover the network fee for transactions Unable to cover %s fee - The interest service isn’t available at the moment. Please try again later. - Earnings unavailable + The Yield mode service isn’t available at the moment. Please try again later. + Yield mode unavailable Unable to load chart... diff --git a/core/ui/src/main/res/drawable/img_visa_waitlist_promo.webp b/core/ui/src/main/res/drawable/img_visa_waitlist_promo.webp new file mode 100644 index 0000000000000000000000000000000000000000..6da45900589e72a54bffa438bbaf439671cf104d GIT binary patch literal 13438 zcmV-^G=a-fNk&F?GynisMM6+kP&il$0000G0002j007qj06|PpNU03~009{WjU*{b z9ixB2@NXfa|G5s~O5rbI<+hP?%YZ|WZPWRCKSzj&)YK;n9ox25+sazsad#*JAqAik z?u70U1#y>l|KSi~na+lB9_2 zuFSkQ%l6o|ZQF0Nwr%e|*?1k>XxsWsIm@=4mFM%x8xiMZA^J5UAWD){w^<>$x0efX zNvV864FC5u(DVIh;fdjJQB^dWSyX_DiQ(5G47;)qF{#WDb zVV##5DXZ`zx#fB5z0`j}r@=Eow1m7bS*`nr|dz>Ck$tZih( ziYvUB7d^v|W*1guM3c$Yv!l13o?c7Hjzz-$nZECNrKP@KP?oc*_xQ(euIjJJNO@7F z@1Guxd0u5nG-D~Wrq1BQudkx+d44#zEI;b|XGA?e>(tCJtm&)%vZ)pPn!L;Hu5yi= z-Q@-c1<&+iVUq{CT+ckWoVemP_q)Ya?sKziU2(O$+~sOlTom?g?7VilaFfS9=mEC~ zdpeRA9a|o}?HOTr$8UbT9JtXt!VZu26PM#V_CsNp$L0Ie$E(6V+s}WIHZFO=PFu?< zY2#sGug7Weba9v3xG!y9Rchnmv{9@!t|&ozwwWU&hrPj;+UZL{LIKSb-h)>W%Fa<8zR zd0njd@(@5;!fwU!WC*dd_;_A#RGgWrXD;AirG2*~%6DWS&`HL1*QvO&BM~dU#=N(=rJKph3 z*oL3;EA@3neG8XRe0=3=))&oc1GS3dPcQ0GZO}aVVgETK`?n7?$49;qLL+DAoZ|S= zTMjV(ZDyzD%R~Odbp&z4&6?u@M384dK|*+6bKDUUM#?8igh9=S;yCYgKp~$Q1QH8d zG+*vRI)J9yF4b{YAW1jRqj-Bsaa?#(Fo;p;qwq29ZJIxG-;Sx38u@&jc&U95kqhWR zYNO^jw-mVm_7yiI6i3d@sm4*kz95Vq(tLS{!~(DdEaf(6j>~cptxlo6uuXI1UPlgx za9gfjGphfYk9aJCP-bSk=D008cph*I1k_zEx{TzK#kzv-??`Yn2t`0LPy)3Bn&aNU z&;L!!nzW>P(W-Mmm^cHWu^Uxa??{EP743mrRL7%29}%o7b~R~^(@qip2U7a#BAWR~ zbKtFXp{mV@J5*O6hEzR=Fd*ICu&DaWUvY5SZ7R>3JfbLxWu}J(*U52FEQc?Lw)0{wcO~!_9 z-4_s5+kg*M$9+hClkFDL;=`&V?-E3df`S9zN$8#oAlH-)!^c#|1IUI`k?pGE#B&fV zg2-aC>VSIz0qviIMBBHhI&K3pq!`IKyG?bRTS>a;=758$BXloSq(%CGH??=r6Ype< zPwM{iS4zwd?v$4JKy|FU!Oe_B+o`*HH&_P>G&bvwTYR*KAxrIVQXP@INDtitliPG( zu65%>#jU#I!S!iS+MiS%Sywn(F@@3n%0Cid8k7#}j=PwOE{->JN7dPB1UE0}J|1?e zNU!OQy5r`MwU5Z+5RT}MbIZY9{784e1K{p%9?%_^i5F}pU`WZ13AHivt7&k65%OktX^q3b>I6U$#u#xiuuo$w zwf_Ide;5J)5DF2C5jEJLEXEo({pZKeeD{quLc`5WjmGq}t9dxuHop3^uYLK4|9Zb+ zHbuq}vMHgUV`;dd>7QTt+>ieG=CS@ca=ICiL84+L7wlCnceLkdd%P)p+9?Ny7L0M= zg(2Y6 z^s2LSg61G=k^M}d&1{TNoX)%Tz+zu>M|;h5d3EuH<#|y|yUk_| zFhAB&JNU_P{>fF@e8Z5MyIRUWSrL89Ij71g3|(J6hVhgIq9Vw!rN|7Rs7!=`|T>P2&RF%-m{EP7cKf z7a2;;~&5naG>E$ zLl9D3Y}S=?GnAL$<3Fga^Q$m-qA%Xr(L9x8n`JN{g8C>RxCJBHzm970(@N>FBH(nImm*@+||{P3-|6 z1v|{(FW1DNZ0D1B_K8al*`;ydI5ptdDN}WxEj*7>6^>GQDhewzhZHj$7Y6jBA_$ z(JnJFoCaf%vZEn4l~^Tf-vkMzS=za=EMm#TQo3hjxTU`TlfeYtoFi;Lu^y*j)kqwj z`OPJ?ENCpdb(_-iH~ac;om6Su{py#BU0*hPn~!|!d*4}W7hJiLb-)1H7GTM%^I=CH zaAL4>+Y;6XEUUHCx>|A80nqV>bFa;@J*|u!tKIR@uG;?D6}G~A7C`2C{*{35mb`VA zrNv{!QkjWzNwa8a7GBy|a(;Ed#UzI64W@CPR@B*5x(cuQ(wl#>y)z9PZ8wKnCpJcTTbLy z)gcuM29c^?2{hR|I5wLRqfZcgQ)ZYa})h{5dPEclMqEo?aOhvugsj6cuL|Ysr<@gkV`|D9ur<%un660W2hJ(N~vHMwCBkZZZxFvd2;B_)j`%5RXTk;xnC{X5o z(O{M2WG)b?pe%lLkoZoR*?dbt*9n{j0`<$?GHa_ijoTsyv%orWM!QwqA!k}>O#Ky_mD1cN|O4zjCx(h6yT?muRQNDM%J6?MCX z*v0x6XaoYF{bXn46;KN9=@_UWh9;?^INai#7`Rkk0>D~F5eSBWC=6@|ftzBW2jmDz z#Zv8*D#R)mBV=Puc0@xeh>Rf|4gBa33Q@6J#zOk~Sw1PMQ-8^?99_ zS0RWWf@>=ijVsNe+NNmVMr%LF&`jNboR(|prd5yP&Hb($~&pp!Y zNp{&OrZ8&F3#@hqf>EbMY`IcrAsf(!#%sU=s7`*JhiGQBZb~^zC2(D*&6dTI%!1I= zja5escYzYKS&-O^Gwg2qf6ibc(MKp+H#mWTAulZSKCAx z_RJ_^zH=nQBSBy^1g^THF$88)d@;QFaum(3I+U zYX?r0rryP1TH({#&+UCQ(b?R6D~00%Jo1yLqtgY#*)!m*IUwxbn{IF4(E;GNRXqKn zL%UtqE&u>lP&go_CIA3Xf&iTXD%b$n06uLnlSd>Xq9G|YEC7HFiA}$%&pO9odhl(l zKe^rP`rkU9W${T&2Z`>pF=|9AF_;j8;c`(OKif;;Ka1?Avp?uOLO+M|hkBp6=nLy-`;SF0w(~Fa zkMJJAAI!g<|G@RL{>O)>*Z=PO0RJuj8UMfif4tZFAO1hydVBq^{pX|yrkDT!bf3BY z#hDm_y$grZPp}Bks9CE+ z)jpGp$hiwW10`e0Ml}P--6`PUTu}16jOB}k1 zc&k*2mpZ6Xbj;P6dYp5)E=mCzar18sn^V`4&-RogApQNup#G!L>QFZ>E{YyGjaWqa zG$gLwvB$g8TUjR;+3_vJN}9wNWO$(!pc?_sJT(K-r0!fZIOgra5_te4uF$caV@EA; z_;KvZ{uPyP9KiPG02d))2I-JXqwyMh@6!R-hbJW3q+sB`P~#!9W9bf^j%vnrN4y8Q zDez@-H{o&+idg5tnCO$3D|^^j*?OD@4@NM{w_+5P|FA%%`3PKIAM`Y;Gi7Epb&;g+ z%l**`?hAt@=CS$coghQ%7$Th+OurQIPX{(+d-t_{ z9+4gEvp~N{;@l<*f^l)Q8K{siIYM;du-H)+d}> z#;IU~#6eMqNyKl0GxWH){kSHvP)@Df&6f>cN)?&w5tai2F9(o;?^o{43b`eeDU3x$ zw6>FqXm9e4q2;niuv;ZvZXU1gPCkd=*ZREEMRxUqj(+?dN4c%mZ${38YOVg1KO z^Hc@%e-9fXN4%RnGa+Tp!tgJ>vLI+rUGUB%tuJxV8?IH1L1Wxm=OX|JfX&YR&k~Y{ z>8I%O<7+Hz@hT%uD)pdw31!*WK2`uAxuFXX8#>1ti z;dkiERJxKQZ6^1^hweYjD3@hU<4W4^ZNLEj{szzh00Eo(&kQFYMbR%-Id7_WQs8l$ zr4HZ!O_j9Zs&D>NpbLJ>*d^GvrwM=lS4wY!i(`Bl-S2vmh&`PQEn21-4@uGRYancz z?_cVH^fOc%hPAvGzC9!KLmx5VJ1lD9&tTVEfrWE#cFqOVd)=|dHtHs5tI1IgE96`v z3rJDWe6PCTn(6ovG|>TfULg{el{*g|x1WO7qjeyJv-4E%gd}C(+JD1z0>#t(Ey9IV zt=elZwPFNc6elQ2?WGdeiO%P_EFWsFjTL{YO9W2tkG9%4H~0cyaXr=};lQ)Ts+Iat z^=i|L<`5HiZY;kXqf^T)exf({Lv?qK^nJb97=i{WC4i3f+JSceiZ#XtD`bCc!7|y0 z(5Y8UTe}O|j7EIw|M;7xPt>omNGeceH`+s-z@l;D)T~}ENeL%Svny1JpW=XS*b|Aq8aL%9PTM z_^JSVoy{1PvhgJnNaJ{Y zSZb4bdY)8D{LyXS0S#Vi*;_GjqpuIo$%zvdxna43u}#H4zJ zjFpk915!5goxbEi$XSRJC7HFyQ10MzpzGgKvj4FG(oqBQ4tkqz6~@~gk;>p`FS4_e za?0>@pN%T1o(3*Up0+K2AJ6x`>ctkg3U#ze=xv}T0*~NEe*WT9oSZ?HhG>mK@}IxF zQ$L*xH-G;U4uQ2;7@U;ns~-mmwR^mx6G7pQIe}fvP8vlB00Vlo(!tYulJf$SJy)wM zZ!ZIL$ZBV#YpWP2zKl+?j_9J(td;QCQlpI&6(AOI)&=R4XauRMwn3QF<w#+5aP`<% zlUvDu9B0~z3aMw)>p~jMYg()TWt%XtGxGOkoid~^RJ8xdwE&!yF{yFvuX4_g-^4fc zSG6MX?tOjJ>}UHYs?Y-5-tzzMc*Eyi zYGT~jxXR=%@UegFT&zY?S_7~xE%NB!NWyoYV(7EDla~0#0}*dv_7!iG*;X8A=lG6uj>Spc` zxOSH|TS`%^SN$U^QYowvA(}S(?Ffpe!R(W|qtAc#zOj-jg*8f>K@5wyvkMff+Z=F< z3(uE>j+vDKU~2=eeyw}E^?WZRENvXX;HDgWvPm%^e>sF9<9Q5+_30sYQzNK1E!tN+ z0pPA_=NU3NCux}fvHbvO^eV&hFiq&}nZc5l2@$PJ!>a z0E_abM+u{ne#4x_&m|?>v~gH8OvY^2iz1_d1gFc&^$K+0(cnBq{Fgt z{iOu79b!n~biR1*3yw9^4VsKhgj*&=%?bGF2PpP;)ET9Ykn6V?QpqHGQry0Zw|u*H z=~F)Nw+UFUejfS)V?S#b1`}otzSjm=tuEYm(js)GyM&yCx;+LB zF+guQKBxYHOW1un?rA9%6=0?2eI-s2KoMytkji1Uv=w9Q0kR_yoylqEd!&{|92Go| zft&Nf*Tdh&gSN~?R_xS(G-<=YUaS>W4N#0N+65wtzT?WBH4p`jgW&jL{|ULBuLSdA z;T`@&LlGsKM!paJLqBK6G*{7h99;#LVy`DrN8Y8%Nj}6to*o6F#rLrwp3)-C)_k1* zaHeNM%xOo%@EJ!~Sy6-yg`xX&G0ux$Af;w!J6y^{&A~|>zG1;v-iwMclh9HKid{NH zeS43=%T=N7LMARWJN~tF^IWt`ibbrd06ms=!{+Ni*T-!~tO0jJ!UU^sb*YS#QKr+* zf{LR;o$eQjYgE>wI@{OnPAWk2RG*y6^DwG48W?hidBhte2ZCO2P`B!Bki{tPTtqlx zW0nZW$wkP8f|vVY;4IdTZYJ>f51zg!&XfKWcLnQ+<=zgBHU%I)@SR;-Gzha|i)0iC2hj z8#M1wn!D@3-LJU9w5uCUg^M@h&1$Qk;8iduNv_ev;dIh9KWZ5w12vgWgyV5y)<@26 zh8Q|%&_1^kZamjW5Y|^y|AcW5NSMVz?{n__Xoss`P%qCWbmT>lu^5>V-q>kPE zaiE7~aO}6P=B_vWMDKbTY{8y36e?PY?ZPEoS-e|$Yp4M9I7F~fplx5+=7B-Rx`O-n>Tl@?tvuhbI*+5jn8{^oE>ipO%See!X2GVvyV@+NO0JUGX$@X*5+X| zzc@qPP2W&BEJWZFl4m@ZUr z4T&G~xge~~=uui6E(3LE-iWdLu2EAd08jnUk^eiA^ZEnu2214rQFV&zghzFy$t&N= z00&B_RuzJw42jAO=B z#+zQNfF`Np!pV?l#rHyfY0qCsw;IE^0dK>?F|5+^yOAvq{Z~CC0EoG=-q4kg^t)8? zQ%j?TjN7H3x^8YN^bB1~jZtqLW``U9L;cmv3PKpisAeZ+%C<<$v?^`Z_Z^S|PXiiL zVS;zm5k&haj$-u5zC01lD}?SXpBnT?vhef&pUHfU^=OCYU-%o} zZxJdQ?%1O39@~%?^0NCxSIs7zSxZ0VOz>XK(i|RNF@IHX}t|7Me z#o=kRy4bhS)2Uexx^Iy{+N>)9;g99PF_U6>+ORQK<~473xG(Qqudef+PPi<%Bezd= zTJw-7(Nl`v6n(Z*RL{(_C+f8E^KXhW5Pvk;(8?bXfs)t>*D+`w4d~WDtrz>AG0M2? zwdC`r>YPdoS^1@{EzJ|En-(Od+rnCQ_6b1Wjn>UW%}&J4Of(JKOx_YhX4qyU1zX2? z6vdPS8@CWEV}Gc(xm3mcPfX?X4B>h$m>II$w~HCx)H?qUSB;m|j9MP2&P^}`|Lukd zoVVVC_(SMNB~!U7jwAEHjDxHTa8uBSAU+T<)FHdMX9fOrP!p>-iy4X0*6wfWavb}2 zhF?&ScCBYiE(RxkGFAmuhUleI%S5DVD%MYY4vGTx9H)fbF5R$fn{if|ok}z@9=s(g z^%GpJ#hxwm7Vt1^=(Ws3E;dIM=Y5YPbb>d8Kn#A7 zz=(OLykb5x4YLLks0`pdpzTZXr^bam(HXlQSX!t-XY%a{X0CxzO=`k_-myl6nYT_UQA5cAM>CfETFQR}Ls9#do``S~_NgG&of9I?ZPDSqG1LG#By z$M-PBY_ftN{0U4GOwjTTri23-e&P0=Dt}}AW_T~bQ61ZrpjxHN_&AoptB^%zr!w%9 z@g}ZfK+*Qd+qX=b>>PC@?RXiC;Voh+U# z*Spv@3vg!p(HQTRgyi2}rNc9ZMFyA3Mn=pJGj$K}n!g7IX>afEQD&5kxowJSc(7(m zu@l!-k0XXW3r~xCmU9miR4>1Cb3c@#+m;*QAPJy-19aRS+KO$S-R(8vrvj zC+$YrtHe6+nkGnUCjuyUF;l;sX8Pf4d53@r%+d#GTL3*w7Rq8RK6R z_w1RwpWRi5)qb1m*T?)MD_37BR(%!RW#dR?r*zJCyV zc+O|xuxEBwiMx1|BTw61{>q(sW)q1j`3yS6Eg(VpZR}LtZx=FU2=&gDeSh@C!j8@S z=$I0x<4=e;FABMyJDK(YE}$o-0VR{7-6vQ~XbeE%fT!Bm#%iRET7cs?)PR9F3k2kM zs+F^@%m+d#|FHw94ENAF;zK^Eo{^=9{%J?cS_i~u5qen*FRZ{b5)^xVC-!9@-+*k} zJ3CbOQ@SL4IbOPMgyCH;h|XJ7;%n;hu-CBu*_7m1VP!D$;jFdg()bA10A4a)vr77_ zg#Sbr#aaM=@)+?sl#}<*SXQ~~eei!x#@`HI5kJROv-;7U;j!P3_dn!r*AWxOtEc77 zd3|g#v)Am8{8pVjE?8-9l$7yYH;IA+Nq!Y?D_iyD%RZ9w-ozl!N4{}PSX!g;`7Gg# zYP{wlCF;mbbH0)-{4Qm}b8Jw&BmoBV@{R`(DtPVvqmbd@%U78Bg{=`ZY}&;R=i3S~ex)}z$$ARFci0|# zLMQaN=79LK9#Y|vL8Hx$0a+YLfxtHEOS;`KoEStn#Wh>c47VYZ4`rl1<4@l_TeyJ3 zHcurgSFh%kviL>Env*m655w#?zPu9t@j=M>vYR0F%d_M!YILddsY~bNaSqyLA-}0KMa)5KDLtl9aandkjN4=w-HW$d1rL zT(7z;aQx)pt>2028+QCh0xRb&6Jv|B(#)^J)(O?C^KRRSIYZ~YQAD$DuG)Yl08?us za_efs>>FTnTvURxIh~{x&6Mna7=UhDVF`-GP9ke?s|o*^#T?UGCk!akI1$(Vpnpkq zVu+GpW>Fs3@WEsqir1rzw zn->4`N^iEZG9PkUCbMrbTF4SPjpRh?Yc^dQ%}o~g{pyq`K@)0gH!`BO)P;Ba@9SxY4;1(+guc0H#c6lt$*8?l1Il!|^9XyWXZS|L|LHp_*1 zbhY@~&=Wv=?RI>Wr1_LzHW2q!Cuwqs7k0uXGOU}3&hodz_E&&+kZL5iHEA4LDZ{L? zO_f0z$~K2nVfdvS$|<^~G*sOHE)oDO7JFabIPoP55VQTm2`A=;keWhe!+)=&vwo8! zFcZqzt9l_823H{5S{MNnl%mnnGWVc0|o{N@K}3?`L+=>P+W<@t;(ZguSjo9~`VX&^QRS5IiNTr*{#0 z{IZ@q4&PRBG8Q`5kUN_yB9^@oBi>O5EaOA5qL^7hnR&GSmTkg`V^XpfY=B~ov1KvI z=<0Qw&K5IV^UwL3m(nNEvgP~3YT`8@jwc_T076SP*2pSlH2XNSve{Yx5`QJW5p{ZD z1CX=zJUTUKsSR?Rc?ryN@;=w=|0@L;g5bH>wXy+JdyxE~af-F>UQgK8l#id%vEz~% z<8Qzl1#-b%ZDzW=P^MYcN?kb2&TAra>-q3c(?tTh$alw|m;sM|+<-c(tBHYZL-FG{ z_ig_9#DcZosy`8$)tE(@@rmL%0&yq+2SSt@$9oojK`^Nb~C-q#X!bnr7mNY)r8~~c{F$Y%k$;01<>ROz$dC_tgssE5& zh~808^o@xY{p*k+v2XaNWwVDFT7!RhtKLGp{^b4$uUTR5wA9*tBnPi~c2}h8>b0=Y z!J&Ehx?M)OI{x0+XrtUd)e6Lif5M~giEdv^9P1+WJ`WEBIZH`E)I_RA=7HP%`D-BM zQ)8NEJ32EXXc|WAZf`&HEGVuSlh{;tLZ9x!>9ZpW&TYpOScl zT*r#qCLj*I@dG6hM;WmH7znw&XnH%An{3BH1WcVq)0iO5dMaQbUcYKmRUg3a@bxE+ zMSqGtvX=CNfY6d~QMBqRf+oMV*$2u{L|^ur5Xm$;NAejxvSCRgs^~@awOp@IrL^LB z6k}qCs*zkGSC^Xh@uy>8^#zBjj`BO*YE2lFZtF=T$y8k^L*}S`i~eBPSTR zr|riz=}Y!$85a&DPMk#}Ji6QCXBzuI$-_5LlXiW$3*(MPxJ*s>1@Z16R1K{5CoICWzl?iW zvYGh$5`JD&uBBokQ_qF}yl@R64jUJ^O%($wHpJYyuJw>~Pp?W<8e9iqUzU-`T_xy0 zQ}1Y>%*J*!r)Mhlg^OkOJ@M$^25{G0W33`)KmL=QZXgXk)|iAK+XnP=B(?38B%h5{ z2m|674SeqOAnVX?7XgxMc=u*i~B%o97Dxqku84q@DtrG+^rN(_q={2Scl{rrD% zjqlzpR0m3v=56TTdp7v}_RQ*jyhAYwn4!tGVrSliV!LjySmcsI{tKs4?a#K(3@3qb zT&l(+`%+n;L_=AB#%H-`!yIG!kaqdh@!SH$jadoT=kb02^*YZEdvM*|u0Iu0BcOk4 z0rkW;Pw$jr(9JK4iKLz}O94m={bja0xtod)mVjp-yOx8n>ao4dr@K7}_v&&ga31>> zrkEGY|CR6G2>;@4d8_H0^BlH_nd!Xi{+i@j2LuyIKCX_{^fOgNpnC3Kgq`Y!@^mMX zbeF&(A90snh#SUyAni@&B;r!H@3EZl!q`I&C|T72a&laiNNjC|@-ust<7d7>Z*6?^ z=DUq$3@c5Jx1iJFG@=v2b?V~s5!QPvb;BmJ&j=i0TzL~HlWVzAmu#T~l`B4)%o&J% z^oGK$uVDw?Cvy!y#VR>z0dj(r>?csFZ~p}f15*}dF}1BVoY0C$3~Gc5N663|L7Fy! zC)=lQ&|JvHG2I>Z4CL3$BMZm&Hkcm#agS;8g@{(U4|v=QqVV3U=OjK?kv}H+Lt~+#5I~%Oz1;sqTO~qjcJ|LLJ3aegK<|8$l+t_dy%N<}27JsM3__z`?&I zio}_Wq(s?>GDO|TUiHP7P@@#94JK6a*wmV8HzHBadxDLTCaT!(ZSQ$o_IYNf$JFft zq^AqAeGsHXzHxkP9|@!p$gl%fOC7*36Q?(D;U5uh&6naF-`Rije%!ksRK?3u<^R172i+YSWrR##0!5o2c5k^f8Q!2rbHcMpO5gyJ!Df7TGhQ7F@Rena-D(W>1A2S8 zywmbeD?Q$Jy$1xpP^jL0mtzOqp%$LQ<7?qSmpC|Mp-_Y{tfsIoEf>g+CEL}hXcc0r zoe4e6?eO;`3`8kVI}A=_En2pQ<0<$l?P=6LzTxh<0^;CY$aM?I-D|g6B3BU%E|AVG!(Jz5;3Q``6DYQU<3`K zqT}Z5Rem?YkWCyam$kH(IlvdVgLKteI&DXl$JEQZCd)sCarH05m4w{f7<(>o@9Bl| zy9Dx>COemTIKcQ$-#wGy0`%G-$sCM~(&|gu$S^wHj?|@7Lj4SA&$iW` z5{@KNI>+6he3c-rE%UMHIW&P&v}#qYZLM=$*aBZ$EW*-XS8(=4FSq+A8AUHI32WmT z@AiT*>0woYeyNk^iS7!+(Qt8qGVd`|KlifMN$6QtBVRYRc4uY&+2R2{cE|g%Y%~%~ z?7!S`^6N>7dsT!pS;PN8*DylwIiGY+^aq`?r~`QYf8D`VH4!wWSXs*dT&O}{o*J+! z|JHe`cKzE7Gz}v;E1J(Mry|z!kI&>AtbEq76me{90R)@dJg}>7oxt^A5x79M;;euh z-mtlaVP_D#d{U;~j8#JQC}0FH!R3qgG4C2B^yN{ha6OmFH))BoEq}bP=+08vXR@R+ g1hh5s*L?sM50)GIDF93|PNT-LFaQ7m000000K3v=lK=n! literal 0 HcmV?d00001 diff --git a/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt b/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt index 09b1d25af8..a0dada9a61 100644 --- a/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt +++ b/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt @@ -18,13 +18,13 @@ import com.tangem.domain.promo.models.PromoId import com.tangem.domain.promo.models.StoryContent import com.tangem.feature.referral.domain.ReferralRepository import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.runCatching import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeoutOrNull -import com.tangem.utils.coroutines.runCatching internal class DefaultPromoRepository( private val tangemApi: TangemTechApi, @@ -49,6 +49,11 @@ internal class DefaultPromoRepository( PromoId.Sepa -> { val isActive = getSepaPromoBanner()?.isActive ?: false + isActive && shouldShow + } + PromoId.VisaPresale -> { + val isActive = getVisaPromoBanner()?.isActive ?: false + isActive && shouldShow } } @@ -59,6 +64,7 @@ internal class DefaultPromoRepository( return when (promoId) { PromoId.Referral -> flowOf(false) PromoId.Sepa -> flowOf(false) + PromoId.VisaPresale -> flowOf(false) } } @@ -134,8 +140,17 @@ internal class DefaultPromoRepository( }.getOrNull() } + private suspend fun getVisaPromoBanner(): PromoBanner? { + return runCatching(dispatchers.io) { + promoBannerConverter.convert( + tangemApi.getPromoBanner(VISA_NAME).getOrThrow(), + ) + }.getOrNull() + } + private companion object { const val SEPA_NAME = "sepa" + const val VISA_NAME = "visa-waitlist" const val STORIES_LOAD_DELAY = 1000L } } \ No newline at end of file diff --git a/domain/promo/models/src/main/java/com/tangem/domain/promo/models/PromoBanner.kt b/domain/promo/models/src/main/java/com/tangem/domain/promo/models/PromoBanner.kt index 7605016350..452445b991 100644 --- a/domain/promo/models/src/main/java/com/tangem/domain/promo/models/PromoBanner.kt +++ b/domain/promo/models/src/main/java/com/tangem/domain/promo/models/PromoBanner.kt @@ -28,4 +28,5 @@ data class PromoBanner( enum class PromoId { Referral, Sepa, + VisaPresale, } \ No newline at end of file diff --git a/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt b/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt index 0fd7070d88..396e1d8e90 100644 --- a/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt +++ b/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt @@ -29,7 +29,9 @@ class ShouldShowPromoWalletUseCase( if (!isReady) return false return when (promoId) { - PromoId.Referral -> true + PromoId.Referral, + PromoId.VisaPresale, + -> true PromoId.Sepa -> { val walletFirstUsageDate = settingsRepository.getWalletFirstUsageDate() if (walletFirstUsageDate == 0L) return false @@ -39,6 +41,7 @@ class ShouldShowPromoWalletUseCase( } } } + suspend fun neverToShow(promoId: PromoId) = promoRepository.setNeverToShowWalletPromo(promoId) private companion object { 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 55390d5b9e..3fefac571e 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 @@ -3,16 +3,17 @@ package com.tangem.feature.wallet.child.wallet.model.intents import arrow.core.getOrElse import com.tangem.common.TangemBlogUrlBuilder import com.tangem.common.routing.AppRoute +import com.tangem.common.routing.AppRoute.Onramp +import com.tangem.common.routing.AppRoute.ReferralProgram import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.navigation.url.UrlOpener import com.tangem.core.ui.extensions.resourceReference -import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase import com.tangem.domain.card.SetCardWasScannedUseCase -import com.tangem.domain.feedback.GetWalletMetaInfoUseCase import com.tangem.domain.core.wallets.UserWalletsListRepository +import com.tangem.domain.feedback.GetWalletMetaInfoUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.models.currency.CryptoCurrency @@ -28,9 +29,11 @@ import com.tangem.domain.settings.NeverToSuggestRateAppUseCase import com.tangem.domain.settings.RemindToRateAppLaterUseCase 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.tokens.model.analytics.TokenSwapPromoAnalyticsEvent.Program +import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent.PromotionBannerClicked 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 @@ -285,11 +288,12 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( analyticsEventHandler.send( when (promoId) { PromoId.Referral -> MainScreen.ReferralPromoButtonDismiss - PromoId.Sepa -> TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( + PromoId.Sepa -> PromotionBannerClicked( source = AnalyticsParam.ScreensSources.Main, - program = TokenSwapPromoAnalyticsEvent.Program.Sepa, - action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Closed, + program = Program.Sepa, + action = PromotionBannerClicked.BannerAction.Closed, ) + PromoId.VisaPresale -> MainScreen.VisaWaitlistPromoDismiss }, ) @@ -303,19 +307,19 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( when (promoId) { PromoId.Referral -> { analyticsEventHandler.send(MainScreen.ReferralPromoButtonParticipate) - appRouter.push(AppRoute.ReferralProgram(userWalletId = userWallet.walletId)) + appRouter.push(ReferralProgram(userWalletId = userWallet.walletId)) } PromoId.Sepa -> { analyticsEventHandler.send( - TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( + PromotionBannerClicked( source = AnalyticsParam.ScreensSources.Main, - program = TokenSwapPromoAnalyticsEvent.Program.Sepa, - action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Clicked, + program = Program.Sepa, + action = PromotionBannerClicked.BannerAction.Clicked, ), ) cryptoCurrency ?: return appRouter.push( - AppRoute.Onramp( + Onramp( userWalletId = userWallet.walletId, currency = cryptoCurrency, source = OnrampSource.SEPA_BANNER, @@ -323,6 +327,10 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( ), ) } + PromoId.VisaPresale -> { + analyticsEventHandler.send(MainScreen.VisaWaitlistPromoJoin) + urlOpener.openUrl(VISA_PROMO_LINK) + } } } @@ -472,4 +480,10 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( null } } + + private companion object { + const val VISA_PROMO_LINK = "https://tangem.com/en/cardwaitlist/?utm_source=tangem-app-banner" + + "&utm_medium=banner" + + "&utm_campaign=tangempaywaitlist" + } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt index 386d7faea0..cb05fdf078 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt @@ -143,5 +143,11 @@ sealed class WalletScreenAnalyticsEvent { data object ReferralPromoButtonParticipate : MainScreen(event = "Button - Referral Participate") data object ReferralPromoButtonDismiss : MainScreen(event = "Button - Referral Dismiss") //endregion + + // region visa waitlist promo + data object VisaWaitlistPromo : MainScreen(event = "Visa Waitlist") + data object VisaWaitlistPromoJoin : MainScreen(event = "Button - Join Now") + data object VisaWaitlistPromoDismiss : MainScreen(event = "Button - Close") + //endregion } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt index bd539e7397..47eae5ba1f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt @@ -58,6 +58,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor( program = Program.Sepa, ) is WalletNotification.ReferralPromo -> MainScreen.ReferralPromo + is WalletNotification.VisaPresalePromo -> MainScreen.VisaWaitlistPromo is WalletNotification.UnlockWallets -> null // See [SelectedWalletAnalyticsSender] is WalletNotification.Informational.NoAccount, is WalletNotification.Warning.LowSignatures, 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 7de4aeda99..72cf06f055 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 @@ -63,9 +63,9 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( flow2 = isReadyToShowRateAppUseCase(), flow3 = isNeedToBackupUseCase(userWallet.walletId), flow4 = seedPhraseNotificationUseCase(userWalletId = userWallet.walletId), - flow5 = shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.Referral), + flow5 = shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.VisaPresale), flow6 = shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.Sepa), - ) { maybeTokenList, isReadyToShowRating, isNeedToBackup, seedPhraseIssueStatus, shouldShowReferralPromo, shouldShowSepaBanner -> + ) { maybeTokenList, isReadyToShowRating, isNeedToBackup, seedPhraseIssueStatus, shouldShowVisaPresalePromo, shouldShowSepaBanner -> buildList { addUsedOutdatedDataNotification(maybeTokenList) @@ -73,7 +73,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( addFinishWalletActivationNotification(userWallet, maybeTokenList, clickIntents) - addReferralPromoNotification(cardTypesResolver, clickIntents, shouldShowReferralPromo) + addVisaPresalePromoNotification(clickIntents, shouldShowVisaPresalePromo) addSepaPromoNotification(userWallet, clickIntents, shouldShowSepaBanner) @@ -220,17 +220,16 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( .map(CryptoCurrencyStatus::currency) } - private fun MutableList.addReferralPromoNotification( - cardTypesResolver: CardTypesResolver?, + private fun MutableList.addVisaPresalePromoNotification( clickIntents: WalletClickIntents, shouldShowPromo: Boolean, ) { addIf( - element = WalletNotification.ReferralPromo( - onCloseClick = { clickIntents.onClosePromoClick(promoId = PromoId.Referral) }, - onClick = { clickIntents.onPromoClick(promoId = PromoId.Referral) }, + element = WalletNotification.VisaPresalePromo( + onCloseClick = { clickIntents.onClosePromoClick(promoId = PromoId.VisaPresale) }, + onClick = { clickIntents.onPromoClick(promoId = PromoId.VisaPresale) }, ), - condition = shouldShowPromo && (cardTypesResolver == null || cardTypesResolver.isTangemWallet()), + condition = shouldShowPromo, ) } 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 c7bfe00b92..1dddf54656 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 @@ -293,6 +293,23 @@ sealed class WalletNotification(val config: NotificationConfig) { ), ) + data class VisaPresalePromo( + val onCloseClick: () -> Unit, + val onClick: () -> Unit, + ) : WalletNotification( + config = NotificationConfig( + title = resourceReference(R.string.notification_visa_waitlist_promo_title), + subtitle = resourceReference(R.string.notification_visa_waitlist_promo_text), + iconResId = R.drawable.img_visa_waitlist_promo, + onCloseClick = onCloseClick, + buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig( + text = resourceReference(R.string.notification_referral_promo_button), + onClick = onClick, + ), + iconSize = 54.dp, + ), + ) + data class Sepa( val onCloseClick: () -> Unit, val onClick: () -> Unit, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/warning/ui/YieldSupplyDepositedWarningContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/warning/ui/YieldSupplyDepositedWarningContent.kt index 9f4529e86f..4a07dbf93a 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/warning/ui/YieldSupplyDepositedWarningContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/warning/ui/YieldSupplyDepositedWarningContent.kt @@ -109,7 +109,7 @@ private fun Content(warningUM: YieldSupplyDepositedWarningUM) { Text( textAlign = TextAlign.Center, - text = stringResourceSafe(R.string.yield_module_explore_sheet_title, warningUM.network), + text = stringResourceSafe(R.string.yield_module_balance_info_sheet_title, warningUM.network), style = TangemTheme.typography.h3, color = TangemTheme.colors.text.primary1, ) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index fa35702753..2131556125 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.29-1268" +tangemBlockchainSdk = "releases-5.29-1295" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "releases-5.29-565" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ diff --git a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/providers/ProviderTypeIdMapping.kt b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/providers/ProviderTypeIdMapping.kt index 831222402b..60a17a7b6c 100644 --- a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/providers/ProviderTypeIdMapping.kt +++ b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/providers/ProviderTypeIdMapping.kt @@ -25,6 +25,6 @@ internal enum class ProviderTypeIdMapping(val id: String, val providerType: Prov KoinosPro(id = "koinospro", providerType = ProviderType.Koinos.KoinosPro), AlephiumTangem(id = "tangemAlephium", providerType = ProviderType.Alephium.Tangem), Blink(id = "blink", providerType = ProviderType.Blink), - Tatum(id = "tatum", providerType = ProviderType.Kusama.Tatum), + Tatum(id = "tatum", providerType = ProviderType.PolkadotLike.Tatum), ; } \ No newline at end of file diff --git a/tangem-android-tools b/tangem-android-tools index 6ef084d2b8..193db8a024 160000 --- a/tangem-android-tools +++ b/tangem-android-tools @@ -1 +1 @@ -Subproject commit 6ef084d2b8bcc4f94d40f38dcdab096c2f0a082b +Subproject commit 193db8a0247a1f33574dcdd5f9ec4dab2c28ea73 From 2288e4d4add6a143f91dbc46218fbf25fbdc88b6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 29 Oct 2025 19:20:39 +0300 Subject: [PATCH 03/19] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index a8cf062a6b..16c0de5855 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit a8cf062a6bb58332458c0f5b43026e062378e5c7 +Subproject commit 16c0de5855d0a75e285a9c84e616dd020f7da4d1 From 79ef677303f28a717dcda499681b5b6970f3fade Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 29 Oct 2025 23:33:15 +0400 Subject: [PATCH 04/19] Updated on 2026-08-14 --- .../yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt index e036e90dd0..7e864db727 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt @@ -29,7 +29,6 @@ import com.tangem.core.ui.res.TangemThemePreview import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.impl.promo.entity.YieldSupplyPromoUM import com.tangem.features.yield.supply.impl.promo.model.YieldSupplyPromoClickIntents -import com.tangem.utils.StringsSigns @Suppress("MagicNumber") @Composable @@ -175,8 +174,6 @@ private fun YieldSupplyTosText(tosLink: String, policyLink: String, onClick: (St Text( text = buildAnnotatedString { - append(StringsSigns.POINT_SIGN) - appendSpace() append(fullString.substring(0, tosIndex)) withLink( link = LinkAnnotation.Clickable( From 47420c3494a2ec778ef01b1635538d3030ff4e4b Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 30 Oct 2025 16:27:54 +0300 Subject: [PATCH 05/19] Updated on 2026-08-14 --- ...alyticsEvent.kt => PromoAnalyticsEvent.kt} | 24 ++++++++++++++++--- ...okenDetailsNotificationsAnalyticsSender.kt | 6 ++--- .../tokendetails/model/TokenDetailsModel.kt | 12 +++++----- .../intents/WalletWarningsClickIntents.kt | 9 +++---- .../analytics/WalletScreenAnalyticsEvent.kt | 6 ----- .../utils/WalletWarningsAnalyticsSender.kt | 10 ++++---- 6 files changed, 40 insertions(+), 27 deletions(-) rename domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/{TokenSwapPromoAnalyticsEvent.kt => PromoAnalyticsEvent.kt} (68%) diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenSwapPromoAnalyticsEvent.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/PromoAnalyticsEvent.kt similarity index 68% rename from domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenSwapPromoAnalyticsEvent.kt rename to domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/PromoAnalyticsEvent.kt index f460d229ff..1dcd4490f4 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenSwapPromoAnalyticsEvent.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/PromoAnalyticsEvent.kt @@ -3,14 +3,14 @@ package com.tangem.domain.tokens.model.analytics import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.core.analytics.models.AnalyticsParam -sealed class TokenSwapPromoAnalyticsEvent( +sealed class PromoAnalyticsEvent( event: String, params: Map = mapOf(), ) : AnalyticsEvent(category = "Promotion", event = event, params = params) { class NoticePromotionBanner( source: AnalyticsParam.ScreensSources, program: Program, - ) : TokenSwapPromoAnalyticsEvent( + ) : PromoAnalyticsEvent( event = "Notice - Promotion Banner", params = mapOf( AnalyticsParam.SOURCE to source.value, @@ -22,7 +22,7 @@ sealed class TokenSwapPromoAnalyticsEvent( source: AnalyticsParam.ScreensSources, program: Program, action: BannerAction, - ) : TokenSwapPromoAnalyticsEvent( + ) : PromoAnalyticsEvent( event = "Promo Banner Clicked", params = mapOf( AnalyticsParam.SOURCE to source.value, @@ -36,6 +36,24 @@ sealed class TokenSwapPromoAnalyticsEvent( } } + // region visa waitlist promo + data object VisaWaitlistPromo : PromoAnalyticsEvent(event = "Visa Waitlist") + + data object VisaWaitlistPromoJoin : PromoAnalyticsEvent( + event = "Button - Join Now", + params = mapOf( + "Program Name" to "Visa Waitlist", + ), + ) + + data object VisaWaitlistPromoDismiss : PromoAnalyticsEvent( + event = "Button - Close", + params = mapOf( + "Program Name" to "Visa Waitlist", + ), + ) + //endregion + // Use it on new promo action enum class Program(val programName: String) { Empty("Empty"), diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenDetailsNotificationsAnalyticsSender.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenDetailsNotificationsAnalyticsSender.kt index c02b4801b9..4b3b18af3e 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenDetailsNotificationsAnalyticsSender.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenDetailsNotificationsAnalyticsSender.kt @@ -4,7 +4,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent +import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification @@ -37,8 +37,8 @@ internal class TokenDetailsNotificationsAnalyticsSender( -> TokenDetailsAnalyticsEvent.Notice.NotEnoughFee( currency = cryptoCurrency, ) - is TokenDetailsNotification.SwapPromo -> TokenSwapPromoAnalyticsEvent.NoticePromotionBanner( - program = TokenSwapPromoAnalyticsEvent.Program.Empty, // Use it on new promo action + is TokenDetailsNotification.SwapPromo -> PromoAnalyticsEvent.NoticePromotionBanner( + program = PromoAnalyticsEvent.Program.Empty, // Use it on new promo action source = AnalyticsParam.ScreensSources.Token, ) is TokenDetailsNotification.KaspaIncompleteTransactionWarning -> TokenDetailsAnalyticsEvent.Notice.Reveal( diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt index 3e626329c4..e0c4f3f024 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt @@ -801,10 +801,10 @@ internal class TokenDetailsModel @Inject constructor( modelScope.launch(dispatchers.main) { shouldShowPromoTokenUseCase.neverToShow(promoId) analyticsEventsHandler.send( - TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( + PromoAnalyticsEvent.PromotionBannerClicked( source = AnalyticsParam.ScreensSources.Token, - program = TokenSwapPromoAnalyticsEvent.Program.Empty, // Use it on new promo action - action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Closed, + program = PromoAnalyticsEvent.Program.Empty, // Use it on new promo action + action = PromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Closed, ), ) } @@ -814,10 +814,10 @@ internal class TokenDetailsModel @Inject constructor( modelScope.launch(dispatchers.main) { shouldShowPromoTokenUseCase.neverToShow(promoId) analyticsEventsHandler.send( - TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( + PromoAnalyticsEvent.PromotionBannerClicked( source = AnalyticsParam.ScreensSources.Token, - program = TokenSwapPromoAnalyticsEvent.Program.Empty, // Use it on new promo action - action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Clicked, + program = PromoAnalyticsEvent.Program.Empty, // Use it on new promo action + action = PromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Clicked, ), ) } 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 3fefac571e..a1c1d2fba1 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 @@ -29,8 +29,9 @@ import com.tangem.domain.settings.NeverToSuggestRateAppUseCase import com.tangem.domain.settings.RemindToRateAppLaterUseCase import com.tangem.domain.staking.StakingIdFactory import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher -import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent.Program -import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent.PromotionBannerClicked +import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent +import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent.Program +import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent.PromotionBannerClicked import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType import com.tangem.domain.wallets.models.UnlockWalletsError import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase @@ -293,7 +294,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( program = Program.Sepa, action = PromotionBannerClicked.BannerAction.Closed, ) - PromoId.VisaPresale -> MainScreen.VisaWaitlistPromoDismiss + PromoId.VisaPresale -> PromoAnalyticsEvent.VisaWaitlistPromoDismiss }, ) @@ -328,7 +329,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( ) } PromoId.VisaPresale -> { - analyticsEventHandler.send(MainScreen.VisaWaitlistPromoJoin) + analyticsEventHandler.send(PromoAnalyticsEvent.VisaWaitlistPromoJoin) urlOpener.openUrl(VISA_PROMO_LINK) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt index cb05fdf078..386d7faea0 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt @@ -143,11 +143,5 @@ sealed class WalletScreenAnalyticsEvent { data object ReferralPromoButtonParticipate : MainScreen(event = "Button - Referral Participate") data object ReferralPromoButtonDismiss : MainScreen(event = "Button - Referral Dismiss") //endregion - - // region visa waitlist promo - data object VisaWaitlistPromo : MainScreen(event = "Visa Waitlist") - data object VisaWaitlistPromoJoin : MainScreen(event = "Button - Join Now") - data object VisaWaitlistPromoDismiss : MainScreen(event = "Button - Close") - //endregion } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt index 47eae5ba1f..6f70e9dd6e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt @@ -4,8 +4,8 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.decompose.di.ModelScoped -import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent -import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent.Program +import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent +import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent.Program import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState @@ -49,16 +49,16 @@ internal class WalletWarningsAnalyticsSender @Inject constructor( is WalletNotification.RateApp -> MainScreen.HowDoYouLikeTangem is WalletNotification.Critical.BackupError -> MainScreen.BackupError is WalletNotification.NoteMigration -> MainScreen.NotePromo - is WalletNotification.SwapPromo -> TokenSwapPromoAnalyticsEvent.NoticePromotionBanner( + is WalletNotification.SwapPromo -> PromoAnalyticsEvent.NoticePromotionBanner( source = AnalyticsParam.ScreensSources.Main, program = Program.Empty, // Use it on new promo action ) - is WalletNotification.Sepa -> TokenSwapPromoAnalyticsEvent.NoticePromotionBanner( + is WalletNotification.Sepa -> PromoAnalyticsEvent.NoticePromotionBanner( source = AnalyticsParam.ScreensSources.Main, program = Program.Sepa, ) is WalletNotification.ReferralPromo -> MainScreen.ReferralPromo - is WalletNotification.VisaPresalePromo -> MainScreen.VisaWaitlistPromo + is WalletNotification.VisaPresalePromo -> PromoAnalyticsEvent.VisaWaitlistPromo is WalletNotification.UnlockWallets -> null // See [SelectedWalletAnalyticsSender] is WalletNotification.Informational.NoAccount, is WalletNotification.Warning.LowSignatures, From 8c5711166f59aa9e60b41abc71915c9abb15d82f Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 30 Oct 2025 18:55:17 +0100 Subject: [PATCH 06/19] Updated on 2026-08-14 --- .../tap/di/domain/ManageTokensDomainModule.kt | 6 ++++- .../tap/di/domain/MarketsDomainModule.kt | 5 ++++ .../managetokens/SaveManagedTokensUseCase.kt | 27 +++++++++++++++---- .../domain/markets/SaveMarketTokensUseCase.kt | 19 ++++++++----- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt index 89bd3b4ca9..c4e44fe950 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt @@ -1,6 +1,5 @@ package com.tangem.tap.di.domain -import com.tangem.domain.wallets.derivations.DerivationsRepository import com.tangem.domain.managetokens.* import com.tangem.domain.managetokens.repository.CustomTokensRepository import com.tangem.domain.managetokens.repository.ManageTokensRepository @@ -10,11 +9,14 @@ import com.tangem.domain.staking.StakingIdFactory import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.walletmanager.WalletManagersFacade +import com.tangem.domain.wallets.derivations.DerivationsRepository import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -74,6 +76,7 @@ internal object ManageTokensDomainModule { multiQuoteStatusFetcher: MultiQuoteStatusFetcher, multiYieldBalanceFetcher: MultiYieldBalanceFetcher, stakingIdFactory: StakingIdFactory, + dispatchers: CoroutineDispatcherProvider, ): SaveManagedTokensUseCase { return SaveManagedTokensUseCase( customTokensRepository = customTokensRepository, @@ -84,6 +87,7 @@ internal object ManageTokensDomainModule { multiQuoteStatusFetcher = multiQuoteStatusFetcher, multiYieldBalanceFetcher = multiYieldBalanceFetcher, stakingIdFactory = stakingIdFactory, + parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.default), ) } diff --git a/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt index 60c8926df6..9b33e83a66 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt @@ -15,10 +15,13 @@ import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.wallets.derivations.DerivationsRepository import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.features.hotwallet.HotWalletFeatureToggles +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -67,6 +70,7 @@ object MarketsDomainModule { multiQuoteStatusFetcher: MultiQuoteStatusFetcher, multiYieldBalanceFetcher: MultiYieldBalanceFetcher, stakingIdFactory: StakingIdFactory, + dispatchers: CoroutineDispatcherProvider, ): SaveMarketTokensUseCase { return SaveMarketTokensUseCase( derivationsRepository = derivationsRepository, @@ -76,6 +80,7 @@ object MarketsDomainModule { multiQuoteStatusFetcher = multiQuoteStatusFetcher, multiYieldBalanceFetcher = multiYieldBalanceFetcher, stakingIdFactory = stakingIdFactory, + parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.default), ) } diff --git a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt index 6c1b21b89b..e6ac3a721d 100644 --- a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt +++ b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt @@ -14,6 +14,10 @@ import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.derivations.DerivationsRepository +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext @Suppress("LongParameterList") class SaveManagedTokensUseCase( @@ -25,6 +29,7 @@ class SaveManagedTokensUseCase( private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher, private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher, private val stakingIdFactory: StakingIdFactory, + private val parallelUpdatingScope: CoroutineScope, ) { suspend operator fun invoke( @@ -53,11 +58,23 @@ class SaveManagedTokensUseCase( currencies = addingCurrencies, ) - refreshUpdatedNetworks(userWalletId = userWalletId, addedCurrencies = savedCurrencies) - - refreshUpdatedYieldBalances(userWalletId = userWalletId, addedCurrencies = savedCurrencies) - - refreshUpdatedQuotes(addedCurrencies = savedCurrencies) + parallelUpdatingScope.launch { + withContext(NonCancellable) { + launch { + refreshUpdatedNetworks( + userWalletId = userWalletId, + addedCurrencies = savedCurrencies, + ) + } + launch { + refreshUpdatedYieldBalances( + userWalletId = userWalletId, + addedCurrencies = savedCurrencies, + ) + } + launch { refreshUpdatedQuotes(addedCurrencies = savedCurrencies) } + } + } } } diff --git a/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt b/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt index 3417a876fd..c5ef6b9cd7 100644 --- a/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt +++ b/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt @@ -1,7 +1,6 @@ package com.tangem.domain.markets import arrow.core.Either -import com.tangem.domain.wallets.derivations.DerivationsRepository import com.tangem.domain.markets.repositories.MarketsTokenRepository import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network @@ -11,6 +10,11 @@ import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher import com.tangem.domain.staking.StakingIdFactory import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.tokens.repository.CurrenciesRepository +import com.tangem.domain.wallets.derivations.DerivationsRepository +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext /** * Use case for saving tokens from Markets @@ -30,6 +34,7 @@ class SaveMarketTokensUseCase( private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher, private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher, private val stakingIdFactory: StakingIdFactory, + private val parallelUpdatingScope: CoroutineScope, ) { suspend operator fun invoke( @@ -69,11 +74,13 @@ class SaveMarketTokensUseCase( currencies = addedCurrencies, ) - refreshUpdatedNetworks(userWalletId, savedCurrencies) - - refreshUpdatedYieldBalances(userWalletId, savedCurrencies) - - refreshUpdatedQuotes(savedCurrencies) + parallelUpdatingScope.launch { + withContext(NonCancellable) { + launch { refreshUpdatedNetworks(userWalletId, savedCurrencies) } + launch { refreshUpdatedYieldBalances(userWalletId, savedCurrencies) } + launch { refreshUpdatedQuotes(savedCurrencies) } + } + } } } From 5a4b35a90e9983dbf9be923df9985fa792bf3e50 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 31 Oct 2025 10:06:00 +0400 Subject: [PATCH 07/19] Updated on 2026-08-14 --- .../core/analytics/models/AnalyticsParam.kt | 6 +++++ .../analytics/TokenScreenAnalyticsEvent.kt | 3 ++- .../api/analytics/YieldSupplyAnalytics.kt | 26 ++++++++++++++----- .../active/model/YieldSupplyActiveModel.kt | 11 ++++++-- .../YieldSupplyActiveFeeContentTransformer.kt | 12 +++++++++ .../approve/model/YieldSupplyApproveModel.kt | 6 +++++ .../YieldSupplyStartEarningEntryModel.kt | 5 +++- .../model/YieldSupplyStartEarningModel.kt | 15 +++++++++++ 8 files changed, 74 insertions(+), 10 deletions(-) diff --git a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt index 5879b1920e..f4690823fb 100644 --- a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt +++ b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt @@ -131,6 +131,12 @@ sealed class AnalyticsParam { override val token: String, override val feeType: FeeType, ) : TxSentFrom("Send&Swap"), TxData + + data class Earning( + override val blockchain: String, + override val token: String, + override val feeType: FeeType, + ) : TxSentFrom("Earning"), TxData } sealed interface TxData { diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt index 3365ce6d87..5c0c30da0d 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt @@ -184,6 +184,7 @@ sealed class TokenScreenAnalyticsEvent( private const val LOADING = "Loading" private const val ASSET_REQUIREMENT = "AssetRequirement" private const val TRUSTLINE_REQUIREMENT = "TrustlineRequirement" + private const val APPROVAL_REQUIRED = "Approval Required" @Suppress("CyclomaticComplexMethod") fun ScenarioUnavailabilityReason.toReasonAnalyticsText(): String { @@ -192,8 +193,8 @@ sealed class TokenScreenAnalyticsEvent( is ScenarioUnavailabilityReason.NotExchangeable, is ScenarioUnavailabilityReason.NotSupportedBySellService, is ScenarioUnavailabilityReason.StakingUnavailable, - ScenarioUnavailabilityReason.YieldSupplyApprovalRequired, -> UNAVAILABLE + is ScenarioUnavailabilityReason.YieldSupplyApprovalRequired -> APPROVAL_REQUIRED ScenarioUnavailabilityReason.UnassociatedAsset -> ASSET_REQUIREMENT ScenarioUnavailabilityReason.TrustlineRequired -> TRUSTLINE_REQUIREMENT is ScenarioUnavailabilityReason.EmptyBalance -> EMPTY diff --git a/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt b/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt index 596a7bb892..9b09110c29 100644 --- a/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt +++ b/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt @@ -77,12 +77,26 @@ sealed class YieldSupplyAnalytics( ), ) - data object ButtonFeePolicy : YieldSupplyAnalytics( + data class ButtonFeePolicy( + val token: String, + val blockchain: String, + ) : YieldSupplyAnalytics( event = "Button - Fee Policy", + params = mapOf( + TOKEN_PARAM to token, + BLOCKCHAIN to blockchain, + ), ) - data object EarnInProgressScreen : YieldSupplyAnalytics( + data class EarnInProgressScreen( + val token: String, + val blockchain: String, + ) : YieldSupplyAnalytics( event = "Earn In Progress Screen", + params = mapOf( + TOKEN_PARAM to token, + BLOCKCHAIN to blockchain, + ), ) data object FundsEarned : YieldSupplyAnalytics( @@ -162,10 +176,10 @@ sealed class YieldSupplyAnalytics( val errorDescription: String?, ) : YieldSupplyAnalytics( event = "Earn Errors", - params = buildMap { - ACTION to action - ERROR_DESCRIPTION to errorDescription.orEmpty() - }, + params = mapOf( + ACTION to action.value, + ERROR_DESCRIPTION to errorDescription.orEmpty(), + ), ) data object ApyChartViewed : YieldSupplyAnalytics( diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt index 8d8bd96071..070ec52cb7 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt @@ -45,7 +45,7 @@ import javax.inject.Inject internal class YieldSupplyActiveModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, - analyticsHandler: AnalyticsEventHandler, + private val analyticsHandler: AnalyticsEventHandler, private val yieldSupplyGetProtocolBalanceUseCase: YieldSupplyGetProtocolBalanceUseCase, private val yieldSupplyGetTokenStatusUseCase: YieldSupplyGetTokenStatusUseCase, private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase, @@ -82,7 +82,7 @@ internal class YieldSupplyActiveModel @Inject constructor( init { analyticsHandler.send( - YieldSupplyAnalytics.EarningScreenInfoOpened( + YieldSupplyAnalytics.EarnInProgressScreen( token = cryptoCurrency.symbol, blockchain = cryptoCurrency.network.name, ), @@ -189,6 +189,12 @@ internal class YieldSupplyActiveModel @Inject constructor( return if (notDepositedAmount > BigDecimal.ZERO) { val formattedAmount = notDepositedAmount.format { crypto(symbol = "", decimals = cryptoCurrencyStatus.currency.decimals) } + analyticsHandler.send( + YieldSupplyAnalytics.NoticeAmountNotDeposited( + token = cryptoCurrency.symbol, + blockchain = cryptoCurrency.network.name, + ), + ) NotificationUM.Warning.YieldSupplyNotAllAmountSupplied( formattedAmount = formattedAmount, symbol = cryptoCurrency.symbol, @@ -243,6 +249,7 @@ internal class YieldSupplyActiveModel @Inject constructor( appCurrency = appCurrency, feeValue = currentFee, maxNetworkFee = maxFee, + analyticsHandler = analyticsHandler, ), ) } else { diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveFeeContentTransformer.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveFeeContentTransformer.kt index bcd2e22076..cc7f66e762 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveFeeContentTransformer.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveFeeContentTransformer.kt @@ -1,5 +1,6 @@ package com.tangem.features.yield.supply.impl.subcomponents.active.model.transformers +import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList @@ -9,6 +10,7 @@ import com.tangem.core.ui.format.bigdecimal.format import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM import com.tangem.utils.transformer.Transformer @@ -22,6 +24,7 @@ internal class YieldSupplyActiveFeeContentTransformer( private val appCurrency: AppCurrency, private val feeValue: BigDecimal, private val maxNetworkFee: BigDecimal, + private val analyticsHandler: AnalyticsEventHandler, ) : Transformer { override fun transform(prevState: YieldSupplyActiveContentUM): YieldSupplyActiveContentUM { @@ -48,6 +51,15 @@ internal class YieldSupplyActiveFeeContentTransformer( val isHighFee = feeValue > maxNetworkFee + if (isHighFee) { + analyticsHandler.send( + YieldSupplyAnalytics.NoticeHighNetworkFee( + token = cryptoCurrency.symbol, + blockchain = cryptoCurrency.network.name, + ), + ) + } + return prevState.copy( currentFee = stringReference(tokenFiatFeeValueText), feeDescription = feeNoteValue, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/approve/model/YieldSupplyApproveModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/approve/model/YieldSupplyApproveModel.kt index 0be362037a..5ccf1e1d6f 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/approve/model/YieldSupplyApproveModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/approve/model/YieldSupplyApproveModel.kt @@ -132,6 +132,12 @@ internal class YieldSupplyApproveModel @Inject constructor( ifLeft = { error -> Timber.e(error.toString()) uiState.update(YieldSupplyTransactionReadyTransformer) + analyticsEventHandler.send( + YieldSupplyAnalytics.EarnErrors( + action = YieldSupplyAnalytics.Action.Approve, + errorDescription = error.getAnalyticsDescription(), + ), + ) yieldSupplyAlertFactory.getSendTransactionErrorState( error = error, popBack = params.callback::onBackClick, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningEntryModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningEntryModel.kt index d6de1559ac..2037750020 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningEntryModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningEntryModel.kt @@ -59,7 +59,10 @@ internal class YieldSupplyStartEarningEntryModel @Inject constructor( override fun onFeePolicyClick() { analyticsEventHandler.send( - YieldSupplyAnalytics.ButtonFeePolicy, + YieldSupplyAnalytics.ButtonFeePolicy( + token = params.cryptoCurrency.symbol, + blockchain = params.cryptoCurrency.network.name, + ), ) router.push(YieldSupplyStartEarningRoute.FeePolicy) } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt index fdb9493169..09949a382e 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt @@ -3,6 +3,8 @@ package com.tangem.features.yield.supply.impl.subcomponents.startearning.model import arrow.core.getOrElse import com.tangem.blockchain.common.TransactionSender import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.analytics.models.Basic import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer @@ -252,7 +254,20 @@ internal class YieldSupplyStartEarningModel @Inject constructor( }, ifRight = { yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Enter) + val event = AnalyticsParam.TxSentFrom.Earning( + blockchain = cryptoCurrency.network.name, + token = cryptoCurrency.symbol, + feeType = AnalyticsParam.FeeType.Normal, + ) analytics.send(YieldSupplyAnalytics.FundsEarned) + yieldSupplyFeeUM.transactionDataList.forEach { + analytics.send( + Basic.TransactionSent( + sentFrom = event, + memoType = Basic.TransactionSent.MemoType.Null, + ), + ) + } val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value if (address != null) { From 7219bafcab143548c0c32ee02a33151d5f3172f4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 31 Oct 2025 11:17:03 +0200 Subject: [PATCH 08/19] Updated on 2026-08-14 --- .../impl/presentation/model/StakingModel.kt | 51 +++++++++++-------- 1 file changed, 31 insertions(+), 20 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 3c8aa515c4..3ae4a70812 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 @@ -168,6 +168,7 @@ internal class StakingModel @Inject constructor( } private var isAccountInitialized: Boolean = true + private var isTonHeatupCase: Boolean = false private lateinit var cryptoCurrencyStatus: CryptoCurrencyStatus private var stakingActions: List = emptyList() private var feeCryptoCurrencyStatus: CryptoCurrencyStatus? = null @@ -1012,10 +1013,12 @@ internal class StakingModel @Inject constructor( ) }, ifRight = { - stateController.update(CompleteInitializeBottomSheetTransformer( - cryptoCurrencyStatus = cryptoCurrencyStatus, - minimumTransactionAmount = minimumTransactionAmount, - )) + stateController.update( + CompleteInitializeBottomSheetTransformer( + cryptoCurrencyStatus = cryptoCurrencyStatus, + minimumTransactionAmount = minimumTransactionAmount, + ), + ) balanceUpdater.partialUpdateWithDelay() stateController.update(DismissBottomSheetStateTransformer) @@ -1053,7 +1056,7 @@ internal class StakingModel @Inject constructor( .conflate() .distinctUntilChanged() .filter { - value.currentStep == StakingStep.InitialInfo || isCaseWithUnitializedTonAccount() + value.currentStep == StakingStep.InitialInfo || isTopHeatupCase() } .onEach { maybeStatus -> maybeStatus.fold( @@ -1082,19 +1085,7 @@ internal class StakingModel @Inject constructor( } cryptoCurrencyStatus = status - val isAccountInitializedNew = checkAccountInitializedUseCase.invoke( - userWalletId = userWalletId, - network = cryptoCurrencyStatus.currency.network, - ).getOrElse { - Timber.e(it) - false - } - if (isAccountInitializedNew && !isAccountInitialized) { - isAccountInitialized = true - updateNotifications() - } - isAccountInitialized = isAccountInitializedNew - + checkForTonHeatupCase() setupApprovalNeeded() setupIsAnyTokenStaked() checkIfSubtractAvailable() @@ -1237,6 +1228,26 @@ internal class StakingModel @Inject constructor( ) } + private suspend fun checkForTonHeatupCase() { + val isAccountInitializedNewValue = checkAccountInitializedUseCase.invoke( + userWalletId = userWalletId, + network = cryptoCurrencyStatus.currency.network, + ).getOrElse { + Timber.e(it) + false + } + + if (!isAccountInitializedNewValue && isAccountInitialized) { + isTonHeatupCase = true + } + + isAccountInitialized = isAccountInitializedNewValue + + if (isTopHeatupCase()) { + updateNotifications() + } + } + private fun isExplicitExit(balanceType: BalanceType, pendingAction: PendingAction?): Boolean { return balanceType == BalanceType.STAKED && pendingAction?.type?.isRestake == false } @@ -1256,11 +1267,11 @@ internal class StakingModel @Inject constructor( .getOrElse { false } } - private fun isCaseWithUnitializedTonAccount(): Boolean { + private fun isTopHeatupCase(): Boolean { if (!::cryptoCurrencyStatus.isInitialized) return false return value.currentStep == StakingStep.Confirmation && isTon(cryptoCurrencyStatus.currency.network.rawId) && - !isAccountInitialized + isTonHeatupCase } private companion object { From c976a399802a7ff1bd88c876b48f2a9c7cbe7611 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 31 Oct 2025 14:51:06 +0400 Subject: [PATCH 09/19] Updated on 2026-08-14 --- .../models/YieldSupplyMarketTokenDto.kt | 5 ++-- .../converters/YieldMarketTokenConverter.kt | 4 +-- .../yield/supply/models/YieldMarketToken.kt | 4 +-- .../usecase/YieldSupplyGetMaxFeeUseCase.kt | 2 +- .../impl/main/ui/YieldSupplyBlockContent.kt | 29 ++++++++++++------- .../model/YieldSupplyStartEarningModel.kt | 3 +- 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldSupplyMarketTokenDto.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldSupplyMarketTokenDto.kt index a2d32540f9..d9d6264389 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldSupplyMarketTokenDto.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldSupplyMarketTokenDto.kt @@ -10,8 +10,9 @@ data class YieldSupplyMarketTokenDto( @Json(name = "tokenSymbol") val tokenSymbol: String? = null, @Json(name = "tokenName") val tokenName: String? = null, @Json(name = "apy") val apy: BigDecimal? = null, + @Json(name = "decimals") val decimals: Int? = null, @Json(name = "isActive") val isActive: Boolean? = null, @Json(name = "chainId") val chainId: Int? = null, - @Json(name = "maxFeeNative") val maxFeeNative: String? = null, - @Json(name = "maxFeeUSD") val maxFeeUSD: String? = null, + @Json(name = "maxFeeNative") val maxFeeNative: BigDecimal? = null, + @Json(name = "maxFeeUSD") val maxFeeUSD: BigDecimal? = null, ) \ No newline at end of file diff --git a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/converters/YieldMarketTokenConverter.kt b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/converters/YieldMarketTokenConverter.kt index c66fb73edd..61d15fb639 100644 --- a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/converters/YieldMarketTokenConverter.kt +++ b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/converters/YieldMarketTokenConverter.kt @@ -12,8 +12,8 @@ internal object YieldMarketTokenConverter : Converter when (supplyUM) { is YieldSupplyUM.Available -> SupplyAvailable(supplyUM, modifier) @@ -118,17 +119,23 @@ private fun SupplyContent(supplyUM: YieldSupplyUM.Content, modifier: Modifier = style = TangemTheme.typography.subtitle1, color = TangemTheme.colors.text.primary1, ) - Text( - text = StringsSigns.DOT, - style = TangemTheme.typography.subtitle1, - color = TangemTheme.colors.text.tertiary, - ) - Text( - text = supplyUM.rewardsApy.resolveReference(), - style = TangemTheme.typography.subtitle1, - maxLines = 1, - color = TangemTheme.colors.text.accent, - ) + AnimatedVisibility(supplyUM.rewardsApy != TextReference.EMPTY) { + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + ) { + Text( + text = StringsSigns.DOT, + style = TangemTheme.typography.subtitle1, + color = TangemTheme.colors.text.tertiary, + ) + Text( + text = supplyUM.rewardsApy.resolveReference(), + style = TangemTheme.typography.subtitle1, + maxLines = 1, + color = TangemTheme.colors.text.accent, + ) + } + } } Text( text = supplyUM.subtitle.resolveReference(), diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt index 09949a382e..f9567b4be5 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt @@ -11,7 +11,6 @@ import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.wrappedList -import com.tangem.core.ui.utils.parseToBigDecimal import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrency @@ -136,7 +135,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( if (uiState.value.maxFee != BigDecimal.ZERO) return uiState.value.maxFee val yieldTokenStatus = yieldSupplyGetTokenStatusUseCase(cryptoCurrency as CryptoCurrency.Token) .getOrNull() - return yieldTokenStatus?.maxFeeNative?.parseToBigDecimal(cryptoCurrency.decimals) + return yieldTokenStatus?.maxFeeNative } private suspend fun onLoadFee() { From ad6e2c1f683493d26f41700fb5e525f12a6ae75a Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 4 Nov 2025 17:25:11 +0500 Subject: [PATCH 10/19] Updated on 2026-08-14 --- .../domain/yield/supply/FeeExtensions.kt | 24 +++++++++++++++++++ .../YieldSupplyEstimateEnterFeeUseCase.kt | 9 +++++-- .../YieldSupplyEstimateEnterFeeUseCaseTest.kt | 12 +++++----- .../model/YieldSupplyStopEarningModel.kt | 4 +++- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/FeeExtensions.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/FeeExtensions.kt index 4032d39149..799506d8f2 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/FeeExtensions.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/FeeExtensions.kt @@ -3,6 +3,10 @@ package com.tangem.domain.yield.supply import com.tangem.blockchain.common.transaction.Fee import com.tangem.domain.models.currency.CryptoCurrency import java.math.BigInteger +import java.math.RoundingMode + +private val HUNDRED_PERCENT = 100.toBigInteger() // base 100% +val INCREASE_GAS_LIMIT_FOR_SUPPLY = 112.toBigInteger() // 12% increase fun Fee.fixFee(cryptoCurrency: CryptoCurrency, gasLimit: BigInteger): Fee = when (this) { is Fee.Ethereum.Legacy -> copy( @@ -20,4 +24,24 @@ fun Fee.fixFee(cryptoCurrency: CryptoCurrency, gasLimit: BigInteger): Fee = when ), ) else -> this +} + +/** + * Increase gasLimit for Fee.Ethereum + */ +fun Fee.increaseGasLimitBy(percent: BigInteger): Fee { + if (this !is Fee.Ethereum) return this + val gasLimit = this.gasLimit + val increasedGasPrice = this.amount.value?.movePointRight(this.amount.decimals) + ?.divide(gasLimit.toBigDecimal(), RoundingMode.HALF_UP) + val increasedGasLimit = gasLimit + .multiply(percent) + .divide(HUNDRED_PERCENT) + val increasedAmount = this.amount.copy( + value = increasedGasLimit.toBigDecimal().multiply(increasedGasPrice).movePointLeft(this.amount.decimals), + ) + return when (this) { + is Fee.Ethereum.EIP1559 -> copy(amount = increasedAmount, gasLimit = increasedGasLimit) + is Fee.Ethereum.Legacy -> copy(amount = increasedAmount, gasLimit = increasedGasLimit) + } } \ No newline at end of file diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyEstimateEnterFeeUseCase.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyEstimateEnterFeeUseCase.kt index 58f1a8476f..e3b24f7f96 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyEstimateEnterFeeUseCase.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyEstimateEnterFeeUseCase.kt @@ -6,11 +6,13 @@ import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyEnterCallData import com.tangem.domain.blockaid.BlockAidGasEstimate import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.yield.supply.fixFee import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.transaction.FeeRepository import com.tangem.domain.transaction.error.FeeErrorResolver import com.tangem.domain.transaction.error.GetFeeError +import com.tangem.domain.yield.supply.INCREASE_GAS_LIMIT_FOR_SUPPLY +import com.tangem.domain.yield.supply.fixFee +import com.tangem.domain.yield.supply.increaseGasLimitBy import com.tangem.utils.extensions.isSingleItem import timber.log.Timber @@ -73,7 +75,10 @@ class YieldSupplyEstimateEnterFeeUseCase( ) return transactionDataList.zip(estimatedFees.estimatedGasList) { transaction, estimatedGas -> - transaction.copy(fee = fee.fixFee(cryptoCurrency, estimatedGas)) + transaction.copy( + fee = fee.fixFee(cryptoCurrency, estimatedGas) + .increaseGasLimitBy(INCREASE_GAS_LIMIT_FOR_SUPPLY), + ) } } diff --git a/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/YieldSupplyEstimateEnterFeeUseCaseTest.kt b/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/YieldSupplyEstimateEnterFeeUseCaseTest.kt index 8a2cc75aae..20c7619b9e 100644 --- a/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/YieldSupplyEstimateEnterFeeUseCaseTest.kt +++ b/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/YieldSupplyEstimateEnterFeeUseCaseTest.kt @@ -314,9 +314,9 @@ class YieldSupplyEstimateEnterFeeUseCaseTest { val deployFee = txs.first().fee as Fee.Ethereum.EIP1559 val approveFee = txs[1].fee as Fee.Ethereum.EIP1559 val enterFee = txs.last().fee as Fee.Ethereum.EIP1559 - Truth.assertThat(deployFee.gasLimit).isEqualTo(BigInteger.valueOf(1_000)) - Truth.assertThat(approveFee.gasLimit).isEqualTo(BigInteger.valueOf(2_000)) - Truth.assertThat(enterFee.gasLimit).isEqualTo(BigInteger.valueOf(3_000)) + Truth.assertThat(deployFee.gasLimit).isEqualTo(BigInteger.valueOf(1_120)) + Truth.assertThat(approveFee.gasLimit).isEqualTo(BigInteger.valueOf(2_240)) + Truth.assertThat(enterFee.gasLimit).isEqualTo(BigInteger.valueOf(3_360)) } @Test @@ -353,9 +353,9 @@ class YieldSupplyEstimateEnterFeeUseCaseTest { val deployFee = txs.first().fee as Fee.Ethereum.Legacy val approveFee = txs[1].fee as Fee.Ethereum.Legacy val enterFee = txs.last().fee as Fee.Ethereum.Legacy - Truth.assertThat(deployFee.gasLimit).isEqualTo(BigInteger.valueOf(1_000)) - Truth.assertThat(approveFee.gasLimit).isEqualTo(BigInteger.valueOf(2_000)) - Truth.assertThat(enterFee.gasLimit).isEqualTo(BigInteger.valueOf(3_000)) + Truth.assertThat(deployFee.gasLimit).isEqualTo(BigInteger.valueOf(1_120)) + Truth.assertThat(approveFee.gasLimit).isEqualTo(BigInteger.valueOf(2_240)) + Truth.assertThat(enterFee.gasLimit).isEqualTo(BigInteger.valueOf(3_360)) } private fun getDeployTx() = uncompiled( diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt index 73cfd703d0..5173d8c6cf 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt @@ -16,7 +16,9 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase import com.tangem.domain.transaction.usecase.GetFeeUseCase import com.tangem.domain.transaction.usecase.SendTransactionUseCase +import com.tangem.domain.yield.supply.INCREASE_GAS_LIMIT_FOR_SUPPLY import com.tangem.domain.yield.supply.YieldSupplyRepository +import com.tangem.domain.yield.supply.increaseGasLimitBy import com.tangem.domain.yield.supply.models.YieldSupplyEnterStatus import com.tangem.domain.yield.supply.usecase.YieldSupplyDeactivateUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyStopEarningUseCase @@ -223,7 +225,7 @@ internal class YieldSupplyStopEarningModel @Inject constructor( } }, ifRight = { fee -> - val fee = fee.normal + val fee = fee.normal.increaseGasLimitBy(INCREASE_GAS_LIMIT_FOR_SUPPLY) val feeCryptoValue = fee.amount.value.orZero() uiState.update( From f807fe288f4df901b8971afa532a97684ee86193 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 4 Nov 2025 17:25:53 +0500 Subject: [PATCH 11/19] Updated on 2026-08-14 --- .../supply/api/analytics/YieldSupplyAnalytics.kt | 1 + .../approve/model/YieldSupplyApproveModel.kt | 13 +++++++++++++ .../model/YieldSupplyStartEarningModel.kt | 2 +- .../model/YieldSupplyStopEarningModel.kt | 13 +++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt b/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt index 9b09110c29..32c5975417 100644 --- a/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt +++ b/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt @@ -198,6 +198,7 @@ sealed class YieldSupplyAnalytics( ) enum class Action(val value: String) { + Start("Start"), Approve("Approve"), Stop("Stop"), } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/approve/model/YieldSupplyApproveModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/approve/model/YieldSupplyApproveModel.kt index 5ccf1e1d6f..3e43bf02a5 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/approve/model/YieldSupplyApproveModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/approve/model/YieldSupplyApproveModel.kt @@ -4,6 +4,8 @@ import arrow.core.getOrElse import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.analytics.models.Basic import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer @@ -153,6 +155,17 @@ internal class YieldSupplyApproveModel @Inject constructor( ) }, ifRight = { + val event = AnalyticsParam.TxSentFrom.Earning( + blockchain = cryptoCurrency.network.name, + token = cryptoCurrency.symbol, + feeType = AnalyticsParam.FeeType.Normal, + ) + analyticsEventHandler.send( + Basic.TransactionSent( + sentFrom = event, + memoType = Basic.TransactionSent.MemoType.Null, + ), + ) analyticsEventHandler.send(YieldSupplyAnalytics.ApprovalAction( token = cryptoCurrency.symbol, blockchain = cryptoCurrency.network.name, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt index f9567b4be5..65cc7f76f0 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt @@ -233,7 +233,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( uiState.update(YieldSupplyTransactionReadyTransformer) analytics.send( YieldSupplyAnalytics.EarnErrors( - action = YieldSupplyAnalytics.Action.Approve, + action = YieldSupplyAnalytics.Action.Start, errorDescription = error.getAnalyticsDescription(), ), ) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt index 5173d8c6cf..8610f6a652 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt @@ -2,6 +2,8 @@ package com.tangem.features.yield.supply.impl.subcomponents.stopearning.model import arrow.core.getOrElse import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.analytics.models.Basic import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer @@ -170,6 +172,17 @@ internal class YieldSupplyStopEarningModel @Inject constructor( blockchain = cryptoCurrency.network.name, ), ) + val event = AnalyticsParam.TxSentFrom.Earning( + blockchain = cryptoCurrency.network.name, + token = cryptoCurrency.symbol, + feeType = AnalyticsParam.FeeType.Normal, + ) + analytics.send( + Basic.TransactionSent( + sentFrom = event, + memoType = Basic.TransactionSent.MemoType.Null, + ), + ) val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value if (address != null) { yieldSupplyDeactivateUseCase(cryptoCurrency, address) From c9fca042055a19d7dfa80b031f39b7983c9deedb Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 4 Nov 2025 14:33:31 +0100 Subject: [PATCH 12/19] Updated on 2026-08-14 --- .../ui/tokens/TokenItemStateConverter.kt | 74 +++++++++++++++---- core/res/src/main/res/values/strings.xml | 1 + .../staking/model/StakingIntegrationID.kt | 5 ++ .../staking/usecase/StakingApyFlowUseCase.kt | 17 +---- 4 files changed, 68 insertions(+), 29 deletions(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt b/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt index 273839cc0e..9ba606d735 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt @@ -1,5 +1,6 @@ package com.tangem.common.ui.tokens +import com.tangem.blockchain.common.Blockchain import com.tangem.common.ui.R import com.tangem.core.ui.components.currency.icon.CurrencyIconState import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter @@ -21,6 +22,7 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.currency.yieldSupplyKey import com.tangem.domain.models.staking.YieldBalance +import com.tangem.domain.staking.model.isStakingSupported import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.staking.utils.getTotalWithRewardsStakingBalance import com.tangem.lib.crypto.BlockchainUtils @@ -211,15 +213,22 @@ class TokenItemStateConverter( } if (stakingApyMap.isNotEmpty()) { - val (stakingRate, hasStaked) = findStakingRate( + val stakingInfo = findStakingRate( currencyStatus = cryptoCurrencyStatus, stakingApyMap = stakingApyMap, ) - if (stakingRate != null) { + val rewardTypeRes = when (stakingInfo.rewardType) { + Yield.RewardType.APR -> R.string.staking_apr_earn_badge + Yield.RewardType.UNKNOWN, + Yield.RewardType.APY, + null, + -> R.string.yield_module_earn_badge + } + if (stakingInfo.rate != null) { return resourceReference( - R.string.yield_module_earn_badge, - wrappedList(stakingRate.format { percent(withPercentSign = false) }), - ) to hasStaked + rewardTypeRes, + wrappedList(stakingInfo.rate.format { percent(withPercentSign = false) }), + ) to stakingInfo.isActive } } @@ -229,21 +238,46 @@ class TokenItemStateConverter( private fun findStakingRate( currencyStatus: CryptoCurrencyStatus, stakingApyMap: Map>, - ): Pair { + ): StakingLocalInfo { val stakingKey = currencyStatus.currency.stakingKey() - val validators = stakingApyMap[stakingKey] ?: return null to false + val validators = stakingApyMap[stakingKey] + ?: return StakingLocalInfo(rate = null, isActive = false, rewardType = null) + val yieldBalance = currencyStatus.value.yieldBalance val hasStakedBalance = yieldBalance is YieldBalance.Data - val rate = if (hasStakedBalance) { + + val rateInfo: Pair? = if (hasStakedBalance) { val validatorsByAddress = validators.associateBy { it.address } yieldBalance.balance.items .mapNotNull { it.validatorAddress } - .firstNotNullOfOrNull { address -> validatorsByAddress[address]?.rewardInfo?.rate } - ?: validators.mapNotNull { it.rewardInfo?.rate }.maxOrNull() + .firstNotNullOfOrNull { address -> + val validator = validatorsByAddress[address] + validator?.rewardInfo?.rate?.let { rate -> + rate to validator.rewardInfo?.type + } + } + ?: validators + .filter { it.preferred } + .mapNotNull { validator -> + validator.rewardInfo?.rate?.let { rate -> rate to validator.rewardInfo?.type } + } + .maxByOrNull { it.first } } else { - validators.mapNotNull { it.rewardInfo?.rate }.maxOrNull() + validators + .filter { it.preferred } + .mapNotNull { validator -> + validator.rewardInfo?.rate?.let { rate -> + rate to validator.rewardInfo?.type + } + } + .maxByOrNull { it.first } } - return rate to hasStakedBalance + + return StakingLocalInfo( + rate = rateInfo?.first, + isActive = hasStakedBalance, + rewardType = rateInfo?.second, + ) } private fun createSubtitleState( @@ -353,7 +387,21 @@ class TokenItemStateConverter( fun CryptoCurrencyStatus.Value.isFlickering(): Boolean = sources.total == StatusSource.CACHE private fun CryptoCurrency.stakingKey(): String { - return "${network.backendId}_$symbol" + if (this is CryptoCurrency.Coin && !network.isStakingSupported) return "" + + if (network.isStakingSupported && this !is CryptoCurrency.Coin) { + val isPolygonTokenOnEthereum = this is CryptoCurrency.Token && + this.network.id.rawId.value == Blockchain.Ethereum.id && + this.symbol == Blockchain.Polygon.currency + if (!isPolygonTokenOnEthereum) return "" + } + return "${id.rawCurrencyId}_$symbol" } } + + private data class StakingLocalInfo( + val rate: BigDecimal?, + val isActive: Boolean, + val rewardType: Yield.RewardType?, + ) } \ No newline at end of file diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 8b5e486e5f..143869f7f9 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -1155,6 +1155,7 @@ The amount to stake must be at least %s Staking amount will be rounded to %1$s TRX due to network rules. Unstaking amount will be rounded to %1$s TRX due to network rules. + APR %1$s%% Claim unstaked Stake account fee A staking account is a special account where staked SOL tokens are stored. It is created when you delegate your tokens to a validator to participate in transaction validation and receive rewards. A small fee is charged for creating the staking account, which is returned after the staking is completed. diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegrationID.kt b/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegrationID.kt index ff38b75b71..43e2488895 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegrationID.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegrationID.kt @@ -1,8 +1,10 @@ package com.tangem.domain.staking.model import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchainsdk.utils.toBlockchain import com.tangem.blockchainsdk.utils.toMigratedCoinId import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.network.Network /** * Represents a staking integration identifier. @@ -143,6 +145,9 @@ sealed interface StakingIntegrationID { } } +val Network.isStakingSupported: Boolean + get() = this.toBlockchain().isStakingSupported + /** * Extension property to check if staking is supported for a blockchain. * diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt index 5b277e5aed..3b50f3a63c 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt @@ -1,8 +1,5 @@ package com.tangem.domain.staking.usecase -import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchainsdk.utils.toNetworkId -import com.tangem.domain.staking.model.StakingIntegrationID import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.staking.repositories.StakingRepository import kotlinx.coroutines.flow.Flow @@ -21,22 +18,10 @@ class StakingApyFlowUseCase(private val stakingRepository: StakingRepository) { return stakingRepository.getEnabledYields() .map { yields -> yields.associate { yield -> - val key = composeKey(yield) + val key = "${yield.token.coinGeckoId}_${yield.token.symbol}" val apy = yield.validators key to apy } } } - - // so that cause for api.stakek.it coinGeckoId on BNB Smart chain different how we receive our backendId - // coinGeckoId - binance - // our backendId BNB Smart Chain - binance-smart-chain - // our backendId BNB Beacon Chain - binance - private fun composeKey(yield: Yield): String { - return if (yield.token.symbol == StakingIntegrationID.Coin.BSC.blockchain.currency) { - "${Blockchain.BSC.toNetworkId()}_${yield.token.symbol}" - } else { - "${yield.token.coinGeckoId}_${yield.token.symbol}" - } - } } \ No newline at end of file From 80ca0095f14da4a050fe1034cb9e916e362cab38 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 3 Nov 2025 14:59:47 +0300 Subject: [PATCH 13/19] Updated on 2026-08-14 --- .../tangem/tap/data/DefaultCardSdkProvider.kt | 18 ++++++++++------ .../tap/network/auth/DefaultAuthProvider.kt | 19 +++++++++++++++++ .../tangem/tap/network/auth/di/AuthModule.kt | 2 ++ .../datasource/api/common/AuthProvider.kt | 6 ++++++ .../api/common/config/TangemTech.kt | 18 ++-------------- .../tangem/datasource/di/ApiConfigsModule.kt | 2 -- .../datasource/utils/AddHeadersInterceptor.kt | 15 ++++++------- .../tangem/datasource/utils/HttpClientExt.kt | 7 ------- .../tangem/datasource/utils/RequestHeader.kt | 9 ++++++++ .../api/common/config/ApiConfigTest.kt | 21 ++++++++++++++++--- .../managers/ProdApiConfigsManagerTest.kt | 12 ++++++++--- 11 files changed, 83 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/data/DefaultCardSdkProvider.kt b/app/src/main/java/com/tangem/tap/data/DefaultCardSdkProvider.kt index d113493313..784db9dbc2 100644 --- a/app/src/main/java/com/tangem/tap/data/DefaultCardSdkProvider.kt +++ b/app/src/main/java/com/tangem/tap/data/DefaultCardSdkProvider.kt @@ -15,6 +15,7 @@ import com.tangem.core.analytics.models.ExceptionAnalyticsEvent import com.tangem.crypto.bip39.Wordlist import com.tangem.data.card.sdk.CardSdkOwner import com.tangem.data.card.sdk.CardSdkProvider +import com.tangem.datasource.api.common.AuthProvider import com.tangem.datasource.api.common.config.ApiConfig import com.tangem.datasource.api.common.config.ApiEnvironmentConfig import com.tangem.datasource.api.common.config.managers.ApiConfigsManager @@ -28,6 +29,7 @@ import com.tangem.sdk.nfc.AndroidNfcAvailabilityProvider import com.tangem.sdk.nfc.NfcManager import com.tangem.sdk.storage.create import com.tangem.tap.foregroundActivityObserver +import com.tangem.utils.Provider import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.info.AppInfoProvider import com.tangem.utils.version.AppVersionProvider @@ -48,6 +50,7 @@ internal class DefaultCardSdkProvider @Inject constructor( private val apiConfigsManager: ApiConfigsManager, appVersionProvider: AppVersionProvider, appInfoProvider: AppInfoProvider, + authProvider: AuthProvider, ) : CardSdkProvider, CardSdkOwner { private val observer = Observer() @@ -68,13 +71,16 @@ internal class DefaultCardSdkProvider @Inject constructor( }, ) + val apiEnvironment = Provider { + apiConfigsManager.getEnvironmentConfig(ApiConfig.ID.TangemTech).environment + } + val platformHeaders = RequestHeader.AppVersionPlatformHeaders( + appVersionProvider = appVersionProvider, + appInfoProvider = appInfoProvider, + ) + val apiKeyHeader = RequestHeader.TangemApiKeyHeader(authProvider, apiEnvironment) TangemApiServiceSettings.addInterceptors( - AddHeadersInterceptor( - requestHeader = RequestHeader.AppVersionPlatformHeaders( - appVersionProvider = appVersionProvider, - appInfoProvider = appInfoProvider, - ), - ), + AddHeadersInterceptor(platformHeaders.values + apiKeyHeader.values), ) } diff --git a/app/src/main/java/com/tangem/tap/network/auth/DefaultAuthProvider.kt b/app/src/main/java/com/tangem/tap/network/auth/DefaultAuthProvider.kt index 8982e6031a..f873c4683f 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/DefaultAuthProvider.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/DefaultAuthProvider.kt @@ -2,14 +2,19 @@ package com.tangem.tap.network.auth import com.tangem.common.extensions.toHexString import com.tangem.datasource.api.common.AuthProvider +import com.tangem.datasource.api.common.config.ApiEnvironment +import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.wallets.legacy.UserWalletsListManager +import com.tangem.utils.Provider +import com.tangem.utils.ProviderSuspend internal class DefaultAuthProvider( private val userWalletsListManager: UserWalletsListManager, private val userWalletsListRepository: UserWalletsListRepository, private val shouldUseNewListRepository: Boolean = false, + private val environmentConfigStorage: EnvironmentConfigStorage, ) : AuthProvider { override suspend fun getCardPublicKey(): String { @@ -38,6 +43,20 @@ internal class DefaultAuthProvider( } } + override fun getApiKey(apiEnvironment: Provider): ProviderSuspend { + return ProviderSuspend { + when (apiEnvironment.invoke()) { + ApiEnvironment.MOCK, + ApiEnvironment.DEV, + ApiEnvironment.DEV_2, + ApiEnvironment.DEV_3, + -> environmentConfigStorage.getConfigSync().tangemApiKeyDev + ApiEnvironment.STAGE -> environmentConfigStorage.getConfigSync().tangemApiKeyStage + ApiEnvironment.PROD -> environmentConfigStorage.getConfigSync().tangemApiKey + } ?: error("No tangem tech api config provided") + } + } + private suspend fun getWallets(): List { return if (shouldUseNewListRepository) { userWalletsListRepository.userWalletsSync() diff --git a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt index f1aa594af8..f1ba2de154 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt @@ -28,11 +28,13 @@ internal class AuthModule { userWalletsListManager: UserWalletsListManager, userWalletsListRepository: UserWalletsListRepository, hotWalletFeatureToggles: HotWalletFeatureToggles, + environmentConfigStorage: EnvironmentConfigStorage, ): AuthProvider { return DefaultAuthProvider( userWalletsListManager = userWalletsListManager, userWalletsListRepository = userWalletsListRepository, shouldUseNewListRepository = hotWalletFeatureToggles.isHotWalletEnabled, + environmentConfigStorage = environmentConfigStorage, ) } diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/AuthProvider.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/AuthProvider.kt index da1b1aca5f..002f8656ed 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/AuthProvider.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/AuthProvider.kt @@ -1,5 +1,9 @@ package com.tangem.datasource.api.common +import com.tangem.datasource.api.common.config.ApiEnvironment +import com.tangem.utils.Provider +import com.tangem.utils.ProviderSuspend + /** * Provides auth for tangemTech API */ @@ -12,6 +16,8 @@ interface AuthProvider { suspend fun getCardId(): String + fun getApiKey(apiEnvironment: Provider): ProviderSuspend + /** * Returns map where keys(cardId) associated with cardPublicKey */ diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/TangemTech.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/TangemTech.kt index 8d44291374..96ef551d23 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/TangemTech.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/TangemTech.kt @@ -2,15 +2,13 @@ package com.tangem.datasource.api.common.config import com.tangem.datasource.BuildConfig import com.tangem.datasource.api.common.AuthProvider -import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.utils.RequestHeader -import com.tangem.utils.ProviderSuspend +import com.tangem.utils.Provider import com.tangem.utils.info.AppInfoProvider import com.tangem.utils.version.AppVersionProvider /** TangemTech [ApiConfig] */ internal class TangemTech( - private val environmentConfigStorage: EnvironmentConfigStorage, private val appVersionProvider: AppVersionProvider, private val authProvider: AuthProvider, private val appInfoProvider: AppInfoProvider, @@ -63,20 +61,8 @@ internal class TangemTech( ) private fun createHeaders(apiEnvironment: ApiEnvironment) = buildMap { - put(key = "api-key", value = ProviderSuspend { getApiKey(apiEnvironment) }) + putAll(from = RequestHeader.TangemApiKeyHeader(authProvider, Provider { apiEnvironment }).values) putAll(from = RequestHeader.AppVersionPlatformHeaders(appVersionProvider, appInfoProvider).values) putAll(from = RequestHeader.AuthenticationHeader(authProvider).values) } - - private fun getApiKey(apiEnvironment: ApiEnvironment): String { - return when (apiEnvironment) { - ApiEnvironment.MOCK, - ApiEnvironment.DEV, - ApiEnvironment.DEV_2, - ApiEnvironment.DEV_3, - -> environmentConfigStorage.getConfigSync().tangemApiKeyDev - ApiEnvironment.STAGE -> environmentConfigStorage.getConfigSync().tangemApiKeyStage - ApiEnvironment.PROD -> environmentConfigStorage.getConfigSync().tangemApiKey - } ?: error("No tangem tech api config provided") - } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/ApiConfigsModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/ApiConfigsModule.kt index 57c3c53a26..83ac850e26 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/ApiConfigsModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/ApiConfigsModule.kt @@ -42,12 +42,10 @@ internal object ApiConfigsModule { @Provides @IntoSet fun provideTangemTechConfig( - environmentConfigStorage: EnvironmentConfigStorage, appVersionProvider: AppVersionProvider, authProvider: AuthProvider, appInfoProvider: AppInfoProvider, ): ApiConfig = TangemTech( - environmentConfigStorage = environmentConfigStorage, appVersionProvider = appVersionProvider, authProvider = authProvider, appInfoProvider = appInfoProvider, diff --git a/core/datasource/src/main/java/com/tangem/datasource/utils/AddHeadersInterceptor.kt b/core/datasource/src/main/java/com/tangem/datasource/utils/AddHeadersInterceptor.kt index 5a896ff3e1..3f05524682 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/utils/AddHeadersInterceptor.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/utils/AddHeadersInterceptor.kt @@ -1,5 +1,6 @@ package com.tangem.datasource.utils +import com.tangem.utils.ProviderSuspend import kotlinx.coroutines.runBlocking import okhttp3.Interceptor import okhttp3.Response @@ -12,21 +13,17 @@ import okhttp3.Response [REDACTED_AUTHOR] */ class AddHeadersInterceptor( - private val requestHeaders: Set, + private val requestHeaders: Map>, ) : Interceptor { - constructor(requestHeader: RequestHeader) : this(requestHeaders = setOf(requestHeader)) - override fun intercept(chain: Interceptor.Chain): Response { val requestBuilder = chain.request().newBuilder() - requestHeaders - .flatMap { it.values.toList() } - .forEach { (name, valueProvider) -> - val value = runBlocking { valueProvider() } + requestHeaders.forEach { (name, valueProvider) -> + val value = runBlocking { valueProvider() } - requestBuilder.addHeader(name = name, value = value) - } + requestBuilder.addHeader(name = name, value = value) + } val request = requestBuilder.build() diff --git a/core/datasource/src/main/java/com/tangem/datasource/utils/HttpClientExt.kt b/core/datasource/src/main/java/com/tangem/datasource/utils/HttpClientExt.kt index eb7727aea3..dcc9855b55 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/utils/HttpClientExt.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/utils/HttpClientExt.kt @@ -5,13 +5,6 @@ import kotlinx.coroutines.runBlocking import okhttp3.Interceptor import okhttp3.OkHttpClient -/** Extension for adding headers [requestHeaders] to every [OkHttpClient] request */ -internal fun OkHttpClient.Builder.addHeaders(vararg requestHeaders: RequestHeader): OkHttpClient.Builder { - return addInterceptor( - interceptor = AddHeadersInterceptor(requestHeaders = requestHeaders.toSet()), - ) -} - /** Extension for adding headers [requestHeaders] to every [OkHttpClient] request */ internal fun OkHttpClient.Builder.addHeaders( requestHeaders: Map>, diff --git a/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt b/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt index 9e6b000399..ef2b83b6df 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt @@ -2,7 +2,9 @@ package com.tangem.datasource.utils import android.os.Build import com.tangem.datasource.api.common.AuthProvider +import com.tangem.datasource.api.common.config.ApiEnvironment import com.tangem.datasource.utils.RequestHeader.CacheControlHeader.checkHeaderValueOrEmpty +import com.tangem.utils.Provider import com.tangem.utils.ProviderSuspend import com.tangem.utils.info.AppInfoProvider import com.tangem.utils.version.AppVersionProvider @@ -40,6 +42,13 @@ sealed class RequestHeader(vararg pairs: Pair>) "device" to ProviderSuspend { "${Build.MANUFACTURER} ${Build.MODEL}".checkHeaderValueOrEmpty() }, ) + /** + * Use ONLY for tangemApi (not express or yields) + */ + class TangemApiKeyHeader(authProvider: AuthProvider, apiEnvironment: Provider) : RequestHeader( + "api-key" to authProvider.getApiKey(apiEnvironment), + ) + /** * Use it to avoid crash in okhttp headers */ diff --git a/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/ApiConfigTest.kt b/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/ApiConfigTest.kt index 53392207a9..0aa707e8cb 100644 --- a/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/ApiConfigTest.kt +++ b/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/ApiConfigTest.kt @@ -1,7 +1,12 @@ package com.tangem.datasource.api.common.config import com.google.common.truth.Truth +import com.tangem.datasource.api.common.AuthProvider +import com.tangem.utils.ProviderSuspend +import io.mockk.clearMocks +import io.mockk.every import io.mockk.mockk +import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import timber.log.Timber @@ -12,6 +17,17 @@ import timber.log.Timber @TestInstance(TestInstance.Lifecycle.PER_CLASS) class ApiConfigTest { + private val appAuthProvider = mockk() + private val apiKeyProvider = mockk>() + + @BeforeEach + fun setup() { + clearMocks( + appAuthProvider, + ) + every { appAuthProvider.getApiKey(any()) } returns apiKeyProvider + } + @Test fun `all baseUrls ends with slash`() { // Arrange @@ -41,15 +57,14 @@ class ApiConfigTest { YieldSupply( environmentConfigStorage = mockk(), appVersionProvider = mockk(), - authProvider = mockk(), + authProvider = appAuthProvider, appInfoProvider = mockk(), ) } ApiConfig.ID.TangemTech -> { TangemTech( - environmentConfigStorage = mockk(), appVersionProvider = mockk(), - authProvider = mockk(), + authProvider = appAuthProvider, appInfoProvider = mockk(), ) } diff --git a/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt b/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt index cb64ca1ea5..de6ac569e4 100644 --- a/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt +++ b/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt @@ -12,6 +12,7 @@ import com.tangem.datasource.api.common.config.ApiConfig.Companion.INTERNAL_BUIL import com.tangem.datasource.api.common.config.ApiConfig.Companion.MOCKED_BUILD_TYPE import com.tangem.datasource.api.common.config.ApiConfig.Companion.RELEASE_BUILD_TYPE import com.tangem.datasource.api.common.config.managers.MockEnvironmentConfigStorage.Companion.BLOCK_AID_API_KEY +import com.tangem.datasource.api.common.config.managers.MockEnvironmentConfigStorage.Companion.TANGEM_API_KEY import com.tangem.lib.auth.ExpressAuthProvider import com.tangem.lib.auth.StakeKitAuthProvider import com.tangem.utils.ProviderSuspend @@ -40,8 +41,9 @@ internal class ProdApiConfigsManagerTest { private val stakeKitAuthProvider = mockk() private val appAuthProvider = mockk() private val appInfoProvider = mockk() + private val tangemApiKeyProvider = mockk>() - private val manager = ProdApiConfigsManager(apiConfigs = createApiConfigs()) + private lateinit var manager: ProdApiConfigsManager @BeforeEach fun setup() { @@ -56,9 +58,14 @@ internal class ProdApiConfigsManagerTest { every { appVersionProvider.versionName } returns VERSION_NAME every { expressAuthProvider.getSessionId() } returns EXPRESS_SESSION_ID every { stakeKitAuthProvider.getApiKey() } returns STAKE_KIT_API_KEY + every { appAuthProvider.getApiKey(any()) } returns tangemApiKeyProvider + coEvery { tangemApiKeyProvider.invoke() } returns TANGEM_API_KEY coEvery { appAuthProvider.getCardId() } returns APP_CARD_ID coEvery { appAuthProvider.getCardPublicKey() } returns APP_CARD_PUBLIC_KEY + every { appInfoProvider.osVersion } returns "Android 16" + + manager = ProdApiConfigsManager(apiConfigs = createApiConfigs()) } @ParameterizedTest @@ -94,7 +101,6 @@ internal class ProdApiConfigsManagerTest { } ApiConfig.ID.TangemTech -> { TangemTech( - environmentConfigStorage = environmentConfigStorage, appVersionProvider = appVersionProvider, authProvider = appAuthProvider, appInfoProvider = appInfoProvider, @@ -175,7 +181,7 @@ internal class ProdApiConfigsManagerTest { environment = ApiEnvironment.PROD, baseUrl = "https://api.tangem.org/", headers = mapOf( - "api-key" to ProviderSuspend { MockEnvironmentConfigStorage.TANGEM_API_KEY }, + "api-key" to ProviderSuspend { TANGEM_API_KEY }, "card_id" to ProviderSuspend { APP_CARD_ID }, "card_public_key" to ProviderSuspend { APP_CARD_PUBLIC_KEY }, "version" to ProviderSuspend { VERSION_NAME }, From 7edea4da006c8e6e1ae8adcacacd26df42c368b8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 4 Nov 2025 23:59:26 +0500 Subject: [PATCH 14/19] Updated on 2026-08-14 --- core/res/src/main/res/values-de/strings.xml | 258 ++++++++++++++---- core/res/src/main/res/values-es/strings.xml | 13 +- core/res/src/main/res/values-fr/strings.xml | 10 +- core/res/src/main/res/values-ja/strings.xml | 62 ++++- core/res/src/main/res/values-ru/strings.xml | 29 +- .../src/main/res/values-uk-rUA/strings.xml | 16 +- core/res/src/main/res/values/strings.xml | 53 +++- .../tangem/core/ui/components/label/Label.kt | 5 +- .../usecase/YieldSupplyGetMaxFeeUseCase.kt | 16 +- .../impl/common/entity/YieldSupplyFeeUM.kt | 2 - .../impl/main/ui/YieldSupplyBlockContent.kt | 13 +- .../impl/promo/ui/YieldSupplyPromoContent.kt | 114 +++++--- .../active/model/YieldSupplyActiveModel.kt | 2 +- .../model/YieldSupplyStartEarningModel.kt | 21 +- ...SupplyStartEarningFeeContentTransformer.kt | 11 +- .../model/YieldSupplyStopEarningModel.kt | 2 +- 16 files changed, 467 insertions(+), 160 deletions(-) diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index cec83f8e76..13d5401bc0 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -7,9 +7,9 @@ Falscher Zugangscode. Deine mobile Wallet wird nach %s weiteren Fehlversuchen gelöscht. Falscher Zugangscode. Die App wird nach %s weiteren Fehlversuchen gesperrt. Falscher Zugangscode.\nBitte warte %s Sekunden und versuche es erneut. - Bestätige Deinen zuvor eingegebenen Code, um fortzufahren + Bestätige Deinen Zugangscode, um fortzufahren. Zugangscode erneut eingeben - Lege einen %s -stelligen Zugangscode fest, um Deine Wallet zu entsperren. + Erstelle einen %s-stelliger Zugangscode, um Deine Wallet zu entsperren. Zugangscode erstellen Zugangscode Du kannst nicht mehr erstellen als %1$s Konto/Konten. Archiviere eines, um es neu hinzuzufügen. @@ -20,13 +20,20 @@ Du bist dabei, dich zu erholen \"%1$s”. Konto wiederherstellen Du hast das Limit von 20 aktiven Konten bereits überschritten. Archiviere eines, um es wiederherzustellen. + Konto kann nicht wiederhergestellt werden Archiviert + Das Konto konnte nicht archiviert werden. Bitte versuche es später erneut. + Dieses Konto nimmt am Empfehlungsprogramm teil. + Dieses Konto kann nicht archiviert werden. + Wir konnten kein Konto erstellen. Bitte versuche es später erneut. Konto erstellt Archivkonto Archiv Du archivierst dieses Konto, kannst es aber jederzeit entarchivieren. + Archivierung... Konto Konto gespeichert + Prämien berücksichtigen Kontonummer %s – wird zur Adressableitung verwendet. Konto hinzufügen Speichern @@ -37,6 +44,9 @@ Konto hinzufügen Konto bearbeiten %1$s in %2$s + Hauptkonto + Du hast das Limit von %1$s aktiven Konten bereits überschritten. Archiviere eines zur Wiederherstellung + Konto kann nicht wiederhergestellt werden Konto wiederhergestellt Tippe lange auf ein Konto, um die Konten neu anzuordnen Weiter bearbeiten @@ -78,7 +88,7 @@ Tokens im %1$s -Netzwerk werden von dieser Karte oder Ring aufgrund einer Firmware-Einschränkung nicht unterstützt. Hast du Probleme beim Scannen deiner Karte oder Ring? Diese Karte oder Ring ist für die Zusammenarbeit mit Tangem nicht geeignet - Verwenden %1$s, um Deine Wallet schnell und sicher zu entsperren und alle sensiblen Aktionen zu autorisieren, wie z. B. das Unterschreiben von Transaktionen. Für Hardware-Wallets benötigst Du weiterhin eine Karte zum signieren. + Verwende die %1$s um Deine Wallet zu entsperren und sensible Aktionen wie das Signieren von Transaktionen zu bestätigen. Bei Hardware-Wallets ist zum Signieren weiterhin eine Karte oder ein Ring erforderlich. Standardgebühr Aktiviere die Option Standardgebühr, um die Transaktionsgebühren automatisch festzulegen und die Gebührenseite beim Senden von Geldern zu überspringen. Du kannst bei Bedarf jederzeit zu dieser Seite zurückkehren. Gehe zu den Einstellungen, um die biometrische Authentifizierung in der Tangem-App zu aktivieren @@ -89,7 +99,7 @@ Durch das Entfernen der gespeicherten Geräte werden alle gespeicherten Wallets und deren Zugangscodes aus der App gelöscht. Dadurch werden alle gespeicherten Wallet-Zugangscodes gelöscht. Für jede weitere Interaktion mit dem Wallet ist die Eingabe des Zugangscodes erforderlich. Zugangscode erforderlich - Mit dieser Option wird die biometrische Authentifizierung für vertrauliche Aktionen deaktiviert. Du musst Deinen Zugangscode jedes Mal eingeben, z. B. wenn Du eine Transaktion unterzeichnest. + Diese Option deaktiviert die biometrische Authentifizierung für sensible Vorgänge. Du musst Deinen Zugangscode jedes Mal eingeben, wenn Du eine Transaktion signierst. Zugangscode speichern Bei Interaktionen mit deiner Karte oder Ring wird anstelle des Zugangscodes eine biometrische Authentifizierung abgefragt. Behalte die Wallet in der App @@ -110,15 +120,15 @@ Du hast Deine Wallet erfolgreich gesichert. Diese Wörter können bei Verlust nicht wiederhergestellt werden. Bewahre diese an einem sicheren Ort auf. Sicherung abgeschlossen - Deine geheime Wiederherstellungsphrase ist ein fester Satz von %s Zufällige Wörter, die für den Zugriff auf und die Wiederherstellung Deiner Wallet verwendet werden. - Diese Wörter können bei Verlust nicht wiederhergestellt werden. Bewahre diese an einem sicheren Ort auf. + Deine geheime Wiederherstellungsphrase ist eine feste Folge von %s zufälligen Wörtern, mit denen Du auf Deiner Wallet zugreifefst und sie wiederherstellen kannst. + Diese Worte sind unwiederbringlich verloren. Bewahre diese gut auf. Sicher aufbewahren - Bewahre diese %s Wörter an einem sicheren Ort auf , z. B. in einem Passwort-Manager, und teile diese niemals mit Dritten. + Speicher diese %s Wörter an einem sicheren Ort und gebe diese niemals an andere weiter. Keine Wiederherstellung möglich Wiederherstellungsphrase Gebe diese Wörter niemals weiter. Jeder, der sie erfährt, kann Deine gesamten Kryptowährungen stehlen. Tangem wird Dich niemals danach fragen. Die folgenden %s Wörter sind die Wiederherstellungsphrase Deiner Wallets. Mit dieser Phrase kannst Du Deine Wallet wiederherstellen, falls Du Dein Gerät verlierst. - Schreibe diese %s Wörter der Reihe nach auf und bewahre sie sicher und vertraulich auf - Die volle Verantwortung für die Sicherheit und Sicherung der Wallet und der Wiederherstellungsphrase liegt beim Benutzer, nicht bei Tangem. + Schreibe diese Wörter %s in numerischer Reihenfolge auf und bewahren diese sicher und vertraulich auf. + Du bist vollumfänglich für die Sicherung und Datensicherung Deiner Wallet und Deine Wiederherstellungsphrase verantwortlich. Wiederherstellungsphrase Um deine Kontostände ein- oder auszublenden, flippe einfach das Display deines Geräts nach unten, oder schalte es in den Einstellungen aus. Nicht mehr anzeigen @@ -132,7 +142,7 @@ Du hast die biometrische Authentifizierung auf deinem Telefon deaktiviert und kannst keine Wallets in der App speichern. Um Wallets zu speichern, aktiviere bitte die biometrische Authentifizierung in deinen Telefoneinstellungen. Bei der Bearbeitung Deines Aktionscodes ist ein Fehler aufgetreten. Bitte versuche es später noch einmal. Fehler bei der Aktivierung - Ihr Aktionscode wurde erfolgreich aktiviert. Eine Belohnung wird innerhalb von 14 Tagen auf Ihr Konto gutgeschrieben. + Dein Gutscheincode wurde erfolgreich aktiviert. Die Prämie wird deinem Bitcoin-Konto innerhalb von 14 Tagen gutgeschrieben. Promo-Code aktiviert Dieser Aktionscode wurde bereits verwendet und kann nicht erneut aktiviert werden. Code nicht verfügbar @@ -150,6 +160,13 @@ Token Tokens + Bitte setze das nächste Gerät zurück, um fortzufahren. + Wallet zurückgesetzt + Alle Tangem-Geräte wurden zurückgesetzt. Du kannst nun mit dem Upgrade Deiner Wallet fortfahren. + Erneut aktualisieren + Zurücksetzen abgeschlossen + Du hast nicht all Deine Tangem-Geräte zurückgesetzt. + Du hast nicht alle Deine Tangem-Geräte zurückgesetzt. Deaktiviere diese Option, wenn du nicht möchtest, dass diese Karte oder Ring zum Zurücksetzen von Zugangscodes auf anderen Karten oder Ringe in dieser Wallets verwendet wird. Bitte beachte, dass du dann auch den Zugangscode auf dieser Karte oder Ring nicht zurücksetzen kannst. Ermöglicht die Verwendung dieser Karte oder Ring zum Zurücksetzen des Zugangscodes auf anderen Karten oder Ringe in dieser Brieftasche Zugangspin resetten @@ -175,11 +192,13 @@ Nicht genug ADA Akzeptieren Zugang verweigert + Konto Konten Aktivieren Hinzufügen Zum Portfolio hinzufügen Token hinzufügen + Hinzugefügt Vertragsadresse Alle Erlauben @@ -239,6 +258,7 @@ Aktivieren Aktiviert Fehler + Netzwerkdienstgebühr Umtausch Erkunden Transaktionsverlauf einsehen @@ -250,10 +270,12 @@ Langsam Gebühren Beenden + Entfernen Kostenlos Vom Adressen synchronisieren Erste Schritte + Token erhalten Zum Anbieter gehen Zum Token Verstanden @@ -266,6 +288,7 @@ %1$s übrig Legacy Bitcoin Gesperrt + Gesperrte Wallet Hauptnetz monat Netzgebühr @@ -293,10 +316,12 @@ %1$s — %2$s Weiterlesen Empfangen + Empfohlen Ablehnen Neu laden Umbenennen Erforderlich + Zurücksetzen Speichern Änderungen speichern Suchen @@ -316,6 +341,7 @@ Signieren Signieren und senden Überspringen + Etwas ist schiefgelaufen. Staken Staking Start @@ -350,6 +376,8 @@ Ja Vertragsadresse kopiert! Verfügbare Netzwerke + Die Ableitung Deines Tokens entspricht der Ableitung von %1$s. Dein Token wird diesem Konto gutgeschrieben. + Die Herleitung stammt aus einem anderen Bericht. Vertragsadresse Vertragsadresse ist ungültig Bitte wähle das Netzwerk @@ -412,6 +440,7 @@ WalletConnect-Fehler Du hast eine Karte oder Ring aus einer anderen Wallet verwendet. Tippe auf die Karte oder Ring, die dieser Wallet zugeordnet ist. Nicht genug Geld für die Transaktion. Bitte lade dein Konto auf. + Tausche einen beliebigen Vermögenswert in deinem Portfolio gegen diesen Token. Meine Token Du hast noch keine Token hinzugefügt. Füge Token über den Markt zum Tausch hinzu Kann nicht gegen %s ausgetauscht werden @@ -467,6 +496,7 @@ Anbieter Bester Preis Warnliste der FCA + Beste Wahl Anbieter in FCA-Warnliste Verfügbar bis zu %s Erhältlich bei %s @@ -502,13 +532,20 @@ Es ist ein Fehler aufgetreten. Code: %s. Memo erforderlich Nur diese - Gib das Genehmigungslimit für das ausgewählte Token an + Mit Deiner Zustimmung erlaubst Du dem Smart Contract, Deine Token in zukünftigen Transaktionen zu verwenden. Betrag %s Die Genehmigungsfunktion ist erforderlich, um einer anderen Adresse die Berechtigung zur Verwendung einer bestimmten Menge Ihrer Token zu erteilen. Standardmäßig können Smart Contracts nicht auf deine Token zugreifen, es sei denn, du stimmen zu. Indem du deine Token \"freischaltest\", autorisierst du den StakeKit Smart Contract, sie zu verwenden. Die Miner des Netzwerks erhalten eine Gasgebühr (von dir bezahlt), um diese Aktion in der Blockchain aufzuzeichnen. Du kannst deine Token einsetzen, nachdem du die Genehmigung erteilt hast. Um fortzufahren, musst du Polygon Smart Contract erlauben, deine %s zu verwenden Um fortzufahren, erteile %1s Smart Contracts die Berechtigung, dein zu %2s verwenden. Erlaubnis erteilen Unbegrenzt + Dein Backup wird mit 2 oder 3 Tangem-Karten erstellt. Bewahre diese an separaten & sicheren Orten auf, um sie vor Verlust oder Beschädigung zu schützen – es ist keine Seed-Phrase erforderlich. + Backup mit mehreren Karten + Tangem Wallet hinzufügen + Dein privater Schlüssel wird direkt in der Tangem-Karte generiert und verlässt diese nie. + Schlüsselgenerierung + Alle kryptografischen Vorgänge finden innerhalb des sicheren Chips statt, der gegen Klonen und physische Manipulation zertifiziert ist. + Sicherheit auf Hardwareebene Vorhandene Wallet hinzufügen Neues Wallet erstellen Karte oder Ring bestellen @@ -518,42 +555,67 @@ Im %s Netzwerk Willst Du den Vorgang zur Erstellung des Zugangscodes wirklich beenden? Jetzt sichern - Um die Einrichtung abzuschließen, sicher Deine Wallet und sicher den App-Zugriff mit einem Access Code. + Um die Einrichtung abzuschließen, sicher Deine Wallet und schütze die App mit einem Zugangscode. Jetzt beenden - Wallet-Aktivierung abschließen - Um das Setup abzuschließen, sicher den App-Zugriff mit Access Code. + Wallet-Einrichtung abschließen + Schließe die Einrichtung ab, indem Du die App mit einem Zugangscode sicherst. Wenn dies der Fall ist, musst Du von vorne beginnen. - Bist Du sicher, dass Du den Aktivierungsprozess beenden willst? + Möchtest Du den Aktivierungsprozess wirklich abbrechen? + Hält Deine Kryptowährungen sicher und offline. Schlank wie eine Kreditkarte, sicherer als ein Banktresor. Wenn dies der Fall ist, musst Du von vorne beginnen. Vorhandene Wallet über Google Drive-Backup wiederherstellen Google Drive-Backup - Verbesser Deine Sicherheit sofort mit einer erstklassigen Hardware-Wallet von Tangem. + Erstelle eine neue, sichere Wallet und übertrage Deine Gelder, um zusätzlichen Schutz zu gewährleisten. + Neue Wallet erstellen + Erhöhe Deine Sicherheit mit der überlegenen Hardware-Wallet von Tangem. Hardware-Wallet + Übertrage Deine aktuelle Wallet in die Tangem Wallet. + Aktualisiere Deine aktuelle Wallet Gehe zum Backup - Um Deine Wallet mit einem Zugangscode zu sichern, führe zuerst die Sicherung durch. - Sicherung zuerst beenden - Physische Karten, die Deine Kryptowährung sicher offline speichern. + Bitte sicher Deine Wallet, bevor Du einen Zugangscode erstellst. + Zuerst die Sicherung abschließen + Andere Methoden + Physische Geräte, die Deine privaten Schlüssel sicher offline speichern. Wiederherstellungs-Phrase + Um Deine Wallet auf Hardware umzustellen, erstelle vorher ein Backup. Schlüssel werden in der App gespeichert Sicherung der Seed-Phrase Mobile Wallet erstellen Vorhandene Wallet importieren Diese Wiederherstellungsphrase wurde bereits importiert Mobile Wallet + Wallet dauerhaft entfernen + Diese Wallet wird dauerhaft von Deinem Gerät entfernt. + Bist du dir sicher, dass du das tun willst? + Wallet dauerhaft entfernen + Zum Backup wechseln + Backup anzeigen + Entferne Deine Wallet für immer! + Trotzdem entfernen! + Für diese Wallet existiert ein Backup. Überprüfe dieses bitte, bevor Du sie entfernst, um sicherzustellen, dass Du sie später wiederherstellen kannst. + Wenn Du diese Wallet ohne Backup entfernst, verlierst Du dauerhaft den Zugriff auf Deine Assets. + Diese Wallet dauerhaft entfernen? + Mir ist bewusst, dass ich den Zugriff auf meine Wallet verliere kann, wenn ich sie vor der Entfernung nicht gesichert habe. + Mir ist bewusst, dass durch das Entfernen meiner Wallet diese nicht gelöscht, sondern lediglich von meinem Gerät entfernt wird. + Es wird keine Seed-Phrase mehr benötigt – Deine Tangem-Karte oder Dein Tangem-Ring wird zu Deinem sicheren Backup. + Backup mit Tangem + Ein Upgrade ist nicht möglich. Auf diesem Gerät ist bereits eine Wallet vorhanden. + Wähle ein anderes Gerät. Dieses Gerät kann für das Upgrade nicht verwendet werden. + Bei der Operation ist ein Fehler aufgetreten. Dein Geld bleibt während des gesamten Prozesses sicher und vollständig zugänglich Zugang zu Geldern - Alle privaten Wallet-Daten werden aus der mobilen App entfernt und nur sicher auf Deinem Tangem-Gerät gespeichert + Die Daten Deiner Wallet werden aus der App gelöscht und auf Deinem Tangem-Gerät gespeichert Allgemeine Sicherheit - Private Schlüssel werden von der App auf Deine Tangem-Karte oder Deinen Tangem-Ring verschoben + Die privaten Schlüssel werden von der App auf Ihr Tangem-Gerät übertragen. Schlüsselmigration Gerät scannen Upgrade starten - Du bist dabei, Deine Wallet auf Tangem Wallet zu aktualisieren. Dies wird Dein Vermögen mit cold-storage sicher verwahren. + Du stehst kurz vor dem Upgrade auf unsere Hardware-Wallet. Damit werden Deine Vermögenswerte sicher in Offline-Speichern aufbewahrt. Tangem Wallet Upgrade auf Hardware Wallet - Bewahren Deine Kryptowährungen sicher auf - mit der erstklassigen Hardware-Wallet von Tangem. - Wallet mit einem Hardware-Backup aufrüsten - Diese Informationen wurden mithilfe von KI generiert.\nTippe hier, wenn Du Fehler finden. + Schütze Deine Kryptowährungen mit Tangems erstklassiger Hardware-Wallet. + Rüste Deine Wallet auf Hardware-Sicherheit auf. + Diese Informationen wurden mithilfe von KI generiert.\nTippe hier, wenn Du Fehler findest. Um den Zugangscode zu ändern, halte die Karte oder Ring wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs. Um den Passcode zu ändern, halte die Karte oder Ring wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs. Um die Wallet zu erstellen, halte die Karte oder Ring wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs. @@ -599,6 +661,7 @@ Der ausgewählte Token ist derzeit nicht für Aktionen innerhalb der Krypto-Wallet verfügbar. Aber keine Sorge, du kannst dein Interesse bekunden, indem du den Token hochstufen. Hochstimmen Das Wallet unterstützt nicht mehr als ein Netzwerk + Über diesen Coin Um dieses Asset zu kaufen, zu tauschen oder zu erhalten, füge diesen Deinem Portfolio hinzu Dieses Asset wird derzeit in der Wallet nicht unterstützt. Dieses Asset ist für dieses Wallet nicht verfügbar @@ -634,6 +697,7 @@ Beliebt Staking ist der einfachste Weg, um Belohnungen für Deine Kryptowährung zu erhalten. %s Verdiene bis zu %s APY + Token hinzugefügt Über %s %d börse @@ -779,7 +843,7 @@ Token hinzufügen Du hast eine Backup-Karte oder einen Backup-Ring hinzugefügt. Nach Abschluss des Backup-Vorgangs kannst Du keine weiteren Backup-Geräte hinzufügen. Wenn Du eine weitere Karte oder einen weiteren Ring hast, fügen diesen dem Backup jetzt hinzu. Möchtest Du den Backup-Vorgang fortsetzen? Der Sicherungsvorgang ist teilweise abgeschlossen. Du kannst ihn jetzt nicht beenden. - Die Passphrase ist eine fortschrittliche Sicherheitsfunktion, die von Krypto-Wallets verwendet wird. Sie fügt ein zusätzliches Wort oder eine Phrase deiner Wahl zu der bereits bestehenden Wiederherstellungsphrase hinzu, um einen brandneuen Satz von Adressen zu erzeugen. + Eine Passphrase ist eine optionale Sicherheitsfunktion, die Deiner Wiederherstellungsphrase ein Wort oder eine Phrase hinzufügt und so einen neuen Satz von Wallet-Adressen für zusätzlichen Schutz erstellt. Hinzufügen einer Sicherungskarte oder Ring Karte oder Ring scannen Scanne die Karte oder Ring Nr. %d @@ -807,6 +871,7 @@ Für die Karte oder Ring, die du hinzufügen möchtest, wurde bereits eine andere Wallets erstellt. Wenn du Guthaben auf dieser Wallets hast, hebe es bitte ab, setze diese Karte oder Ring zurück und füge sie als Backup hinzu. Sicher deine Wallet Backups anlegen + Biometrische Daten Lese mehr über die Seed-Phrase @@ -868,6 +933,7 @@ Andere Währungen Beliebte Fiats Suche nach Währung + Die besten Preise erzielen... Sofort Durch die Nutzung der Onramp-Funktionalität stimmst Du den %1$s und %2$s des Anbieters zu. Der Service wird von einem externen Anbieter bereitgestellt. \n Tangem übernimmt keine Verantwortung. @@ -894,7 +960,12 @@ Bitte wähle das richtige Land aus, um korrekte Zahlungsoptionen und Dienstleistungen zu gewährleisten. Einstellungen Du kannst diesen Bildschirm schließen und den Transaktionsstatus auf dem Bildschirm mit den Token-Details überprüfen. + + bis zu %d Tag + bis zu %d Tagen + %s min + Erhältlich ab Du erhältst Der Service wird von einem externen Anbieter bereitgestellt. \n Tangem übernimmt keine Verantwortung. Du kannst diesen Bildschirm schließen und den Transaktionsstatus auf dem Bildschirm mit den Token-Details überprüfen. @@ -959,6 +1030,10 @@ Mir ist klar, dass ich diese Karte oder Ring nicht verwenden kann, um meinen Zugangscode auf den anderen Karten oder Ringe der aktuellen Wallet wiederherzustellen Durch das Zurücksetzen auf Werkseinstellungen wird die Wallet vollständig von der ausgewählten Karte oder Ring gelöscht. Du kannst die aktuelle Wallet nicht wiederherstellen oder die Karte oder Ring verwenden, um den Zugangscode wiederherzustellen. Beim Zurücksetzen auf die Werkseinstellungen wird die Wallet der ausgewählten Karte oder Ring vollständig gelöscht und aus der App entfernt. Es ist nicht möglich, die aktuelle Wallet wiederherzustellen. + Alle Tangem-Geräte wurden zurückgesetzt. + Bei der Aktivierung ist ein Fehler aufgetreten. Bitte setze die Karten nacheinander zurück. + Kartenprüfung fehlgeschlagen + Bitte setze das nächste Gerät zurück, um fortzufahren. Ringbesitzer erhalten bis zum 15.11. 3 provisionsfreie Swaps auf Changelly! Jetzt mit 0 % Gebühren tauschen! Melde dich bei der App an und überprüfe dein Guthaben, ohne die Karte oder Ring zu scannen @@ -1083,11 +1158,11 @@ Bist Du sicher, dass Du den Empfangstoken ändern möchtest? Dadurch werden Dein zuvor eingegebenen Daten zurückgesetzt. Token ändern Tauschen und senden - Mit der Konvertierung fortfahren? Dadurch werden Deine vorherigen Daten gelöscht. + Mit dem Datentausch fortfahren? Dadurch werden Deine vorherigen Daten gelöscht. Konvertierung bestätigen Das Senden einer anderen Währung führt zu deren unwiderruflichem Verlust. Wähle das richtige Empfängernetzwerk - Sende uns ein Token, und wir konvertieren es unterwegs. Dein Empfänger erhält genau das, was er braucht – nahtlos. + Wähle einen beliebige Token aus, den Du bekommen möchtest. Dein Empfänger erhält genau das, was Du ausgewählt hast – nahtlos. Der Empfänger erhält An den Empfänger Zu erhaltender Betrag @@ -1102,11 +1177,12 @@ Name Lass deinen Token für dich arbeiten Eine Netzwerkgebühr ist eine kleine Zahlung, die erforderlich ist, um Deine Transaktion auf der Blockchain zu verarbeiten und zu bestätigen. - Um mit dem Staking zu beginnen, muss Dein TON-Konto mit einer Selbsttransaktion von 1 TON aktiviert werden. Das Guthaben verbleibt in Deiner Wallet – dieser Schritt aktiviert Dein Konto lediglich für das Staking. + Um mit dem Staking zu beginnen, muss Dein TON-Konto mit einer Transaktion von 1 TON aktiviert werden. Das Guthaben verbleibt auf Deinem Konto, dieser Schritt dient lediglichder aktivierung für das Staking. Kontoaktivierung Die Anzahl der zu stakenden Krypros muss mindesten %s betragen Der Stakingbetrag wird aufgrund der Netzwerkregeln auf %1$s TRX aufgerundet. Der Betrag der unstaked wird, wird aufgrund der Netzwerkregeln auf %1$s TRX gerundet. + Effektiver Jahreszins %1$s%% Nicht gestakte beanspruche Gebühr für das Staking-Konto Ein Staking-Konto ist ein spezielles Konto, auf dem eingesetzte SOL-Token gespeichert werden. Es wird erstellt, indem Sie Ihre Token an einen Validator delegieren, um an der Transaktionsvalidierung teilzunehmen und Belohnungen zu erhalten. Für die Einrichtung des Staking-Kontos wird eine geringe Gebühr erhoben, die nach Abschluss des Stakings zurückerstattet wird. @@ -1167,10 +1243,10 @@ Wenn Du im %1$s -Netzwerk mit einem neuen Validator stakest, werden alle zuvor eingesetzten Gelder automatisch an diesen Validator übertragen. Reinvestiert Deine verdienten Prämien in Deinen Einsatzbetrag und erhöht so den potenziellen Gewinn. Mit Restake kannst Du Dein Guthaben von einem Validator zu einem anderen verschieben, ohne dass Du den Stake aufheben musst. - Du bist dabei, Dein gesamtes Guthaben zu staken. Wir empfehlen, einen kleinen Betrag übrig zu lassen, um die Netzwerkgebühren für die Aufhebung des Stakes oder das Einfordern von Prämien abzudecken. - Um mit dem Staking zu beginnen, muss Dein TON-Konto mit einer Selbsttransaktion von 1 TON aktiviert werden. Das Guthaben verbleibt in Deiner Wallet – dieser Schritt aktiviert Dein Konto lediglich für das Staking. + Wenn Du Dein gesamtes Guthaben einsetzt, musst Du beim Aufheben der Einsätze eine Netzwerkgebühr entrichten. Wir empfehlen, einen kleinen Betrag in Deiner Wallet zu belassen, um die Netzwerkgebühren zu decken. + Um mit dem Staking zu beginnen, musst Du zuerst Dein TON-Konto aktivieren. Kontoaktivierung - Um mit dem Staking bei TON zu beginnen, führe zunächst eine ausgehende Transaktion in beliebiger Höhe durch – dadurch wird Deine Wallet aktiviert. + Um mit dem Staking in TON zu beginnen, sende zunächst eine kleine Transaktion an Deine eigene Adresse – dadurch wird Deine Wallet aktiviert. Für den Abschluss der Transaktion können zusätzlich zur Netzwerkgebühr bis zu 0,2 TON erforderlich sein. Nicht genutzte Beträge werden zurückerstattet. Für diesen Vorgang sind zusätzlich zur Netzwerkgebühr 0,2 TON erforderlich. Bitte lade Dein Guthaben auf. TON-Reserve erforderlich @@ -1275,10 +1351,48 @@ Du erhältst Token auswählen Nicht verfügbar + Einzahlung + Streitfall + Transaktion erkunden + Servicegebühren + Gebühr + Schütze Dein Geld, falls Deine Karte verloren geht oder gestohlen wird. Du kannst die Sperre jederzeit aufheben. + Karte sperren lassen? + Einfrieren + Hilfe erhalten + Abgeschlossen + Abgelehnt + Ausstehend + Die Bank hat diese Transaktionsanfrage abgelehnt. + Diese Gebühr dient zur Deckung der Kosten für die Abwicklung Deiner Überweisung. + Abhebung + Guthaben hinzufügen + Aufladeoptionen + PIN ändern + Die Karte ist vollständig für Zahlungen bereit. + PIN-Code erstellt Daten konnten nicht geladen werden. Versuche es später noch einmal. + Karte einfrieren Verstecken + Google Wallet öffnen + Richte Tangem Pay mit wenigen Klicks ein und bezahlen mit Google Pay. + Karte zu Google Pay hinzufügen + Google Wallet öffnen + Tippe auf „Karte hinzufügen“. + Gebe die Kartendaten manuell ein + Verifiziere die Karte mit dem Einmalpasswort (OPT), das an Dein Gerät gesendet wird. + Alles erledigt! Deine Karte ist einsatzbereit. + Karte zu Google Pay hinzufügen + Teile Deine Adresse mit oder zeig den QR-Code. + Es wurden technische Probleme festgestellt. Bitte versuche es später erneut oder kontaktiere den Support. + Empfangen ist jetzt nicht verfügbar Aufdecken + Tausche beliebige Vermögenswerte in Deinem Portfolio gegen eine Karte. Kartendetails + Konto erstellen und Karte ausstellen + Tangem Pay + Status anzeigen + KYC für Tangem Pay in Arbeit Karte erhalten Füge es Deiner Wallet hinzu und bezahle überall mit Deinem Smartphone. Apple Pay & Google Pay @@ -1304,6 +1418,7 @@ Die Geldsendung wird verfügbar, sobald die ausstehende(n) Transaktion(en) im Netzwerk %s abgeschlossen ist/sind. Der Verkauf von %s wird von aktuellen Anbietern nicht unterstützt, aber wir arbeiten daran, weitere Optionen hinzuzufügen. Staking %s wird von aktuellen Anbietern nicht unterstützt, aber wir arbeiten daran, weitere Optionen hinzuzufügen. + Die Genehmigung wurde widerrufen. Dein Guthaben befindet sich weiterhin im Ertragsmodus. Um Aktionen durchzuführen, wechsel bitte in den Ertragsmodus und erteilen die Berechtigung erneut. Generiere XPUB Ausblenden Du bist dabei, dieses Token vom Hauptbildschirm auszublenden. Du kannst es jederzeit über die Seite „Token verwalten“ wieder hinzufügen. @@ -1367,6 +1482,7 @@ Aktiviere Push-Benachrichtigungen und wir benachrichtigen Dich sofort, wenn Gelder eintreffen Verpasse keine Transaktion Neues Wallet hinzufügen + Wenn Du diese Wallet ohne vorheriges Backup löschst, verlierst Du dauerhaft den Zugriff auf Dein Guthaben. Möchtest Du diese Wallet wirklich entfernen? Es ist ein Fehler aufgetreten, bitte scanne deine Karte oder Ring, um sich anzumelden Dieses Wallet wurde bereits gespeichert, du kannst ein weiteres hinzufügen @@ -1382,15 +1498,19 @@ Guthaben und Limits Zugangscode + Aktivierung des Kontos Bitte wähle die Wallet aus, mit der Du den Registrierungsprozess gestartet hast, um die Transaktion zur Erstellung Deines Kontos auf der Blockchain zu signieren Möchtest Du den Vorgang wirklich beenden? Du kannst später dort fortfahren, wo Du aufgehört hast. Das wird nicht lange dauern. Wir richten gerade Dein Konto ein. Das wird nicht lange dauern. Wir schließen die Aktivierung ab. Alles wird vorbereitet! + Andere Wallet PIN-Code erstellen PIN wurde nicht akzeptiert. Versuche es erneut oder verwende einen anderen Code. Ungültige PIN: Sequenzen oder Wiederholungen vermeiden Schon kann es losgehen! + Halte die Tangem-Karte bereit und tippe diese um zum Genehmigen. + Tangem Wallet vorbereiten Du kannst Deine Verbindung \n auf der Website des Drittanbieters \n herstellen und zurück zur Tangem-App gelangen Zur Website gehen Wallet wählen @@ -1402,6 +1522,13 @@ Freischalten Scanne Deine Karte, um den Zugriff freizuschalten Benötigte Freischaltung + Wähle aus, wie Du Deine Wallet hinzufügen möchtest. + Scanne Deine Tangem-Karte oder Deinen Tangem-Ring, um sie wiederherzustellen oder aus einer anderen Wallet zu importieren. + Hardware-Wallet erstellen + Möchtest Du eine Tangem-Wallet kaufen? + Seed-Phrase importieren + Stell Deine Wallet auf Deinem Smartphone wieder her oder importieren diese aus einer anderen App – praktisch, aber weniger sicher als eine Tangem-Karte. + Was soll man wählen? Blockchain ist nicht erreichbar. Versuche es später nochmal Karte oder Ring scannen Dieses Wallet wurde bereits früher aktiviert. \n Wenn dies nicht von Dir durchgeführt wurde, wende Dich bitte an den Support. \n Tangem verkauft niemals Wallets zusammen mit vorgenerierten Zugangscodes. @@ -1422,6 +1549,8 @@ Falsche Karte oder Ring in der Tangem App ausgewählt Transaktion aus Dapp-Daten konnte nicht erstellt werden. Code: %s Es ist ein unbekannter Fehler aufgetreten. Fehlercode: %d. Wenn das Problem weiterhin besteht, wende dich bitte an unseren Support + Mehrteilige Transaktion + Zur erfolgreichen Abwicklung wird Deine Transaktion in mehrere Teile aufgeteilt. Du musst Deine Karte mehrmals ans smartphone halten, um sie abzuschließen. Keine geöffneten WalletConnect-Sitzungen Hoppla. Keine Sitzungen. WalletConnect-Sitzung konnte nicht gekoppelt werden: %1$s @@ -1433,29 +1562,32 @@ Mit dieser Karte oder Ring kann keine WalletConnect-Sitzung hergestellt werden Dieses Netzwerk wird nicht unterstützt. Bitte wähle ein anderes Netzwerk. Netzwerk auswählen + Die Transaktion wird verarbeitet. Bitte halte Deine Karte mehrmals an, um sie abzuschließen. + Transaktion läuft WalletConnect-Sitzungen Mit dApps verbinden WalletConnect Das Herstellen der Verbindung kann einige Sekunden dauern + Tangem-Wallet erstellen Von %s - Kaufe eine Tangem Wallet – physische Karten, die Deine Kryptowährungen sicher offline speichern. + Kaufe eine Tangem Wallet – ein physisches Gerät, das Deine privaten Schlüssel sicher offline speichert. Hardware-Wallet - Eine sichere Wallet wird in Sekundenschnelle auf Deinem Telefon erstellt. + Erstelle in Sekundenschnelle eine sichere Wallet auf Deinem Smartphone. Mobile Wallet - Was soll ich wählen? - Besitzt Du bereits eine Tangem Wallet? + Was auswählen? + Verwendest Du bereits eine Tangem-Wallet? Jetzt scannen - Wähle, wie Du Deine Wallet erstellen möchten + Wähle eine Methode zur Einrichtung Deiner Wallet. Möchtest Du eine Tangem-Wallet kaufen? Jetzt kaufen - Eine vorhandene Wallet wiederherstellen, die Deinem Google Drive-Backup gespeichert ist + Stelle Deine bestehende Wallet über ein Google Drive-Backup wieder her. Importieren aus Google Drive Vorhandenes Wallet hinzufügen Physische Karten, die Deine Kryptowährung sicher offline speichern. Scanne eine Tangem-Wallet - Deine Seed-Phrase, um Deine Wallet wiederherzustellen + Importiere eine bestehende Wallet mit Deiner Wiederherstellungsphrase. Wallet importieren - Importieren einer Wiederherstellungsphrase + Wiederherstellungsphrase eingeben Du hast Deine Wallet erfolgreich gesichert. Wallet importieren Import abgeschlossen @@ -1468,7 +1600,7 @@ Jetzt mit 10 % Rabatt kaufen Greife auf 13.000+ Kryptowährungen zu. Kaufe, verkaufe, tausche und stake Sie mit einem einzigen Fingertipp.\nVerbinde bis zu drei Karten für ein Backup. Entdecke die Tangem Wallet - Geheimcode zum Schutz dieser Wallet. Wird für Anmeldung und Signaturen verwendet. + Dieser geheime Code schützt Deine Wallet und wird zum Einloggen und Signieren von Transaktionen verwendet. Zugangscode festlegen/ändern Zugangscode ändern Bleib stets über eingehende Wallet-Transaktionen und Tangem-Updates auf dem Laufenden. @@ -1648,7 +1780,7 @@ Keine Wallet-Änderungen erkannt Es wurden potenzielle Risiken oder bösartiges Verhalten erkannt. Das Verbinden oder Signieren von Transaktionen kann zum Verlust von Geldern führen. Bekanntes Sicherheitsrisiko - Öffne die Web3-App und wähle die Option WalletConnect + Öffne die Web3-App und wähle die Option WalletConnect. Anfrage von Trotzdem signieren Art der Signatur @@ -1663,6 +1795,20 @@ URI bereits verwendet WalletConnect Verdächtige Transaktion + Besitzt Du bereits eine Tangem Wallet? + Tausende von Vermögenswerten + Erstklassige Hardware-Wallet + Schnelle Lieferung + Mit einem Fingertipp starten + Nahtlos und sicher + Einfach zu bedienen + Erstelle eine Hardware-Wallet mit Tangem. Schlank wie eine Bankkarte, sicher wie ein Banktresor. + Erstelle oder importiere eine Software-Wallet + Erstelle oder importiere eine Software-Wallet auf Deinem Telefon + Beginne mit Mobile Wallet + Andere Methode + Tangem Hardware Wallet verwenden + Mehr erfahren & kaufen Verwerfen Du hast eine unterbrochene Sicherung. Möchtest du diese fortsetzen? Ja, fortsetzen @@ -1679,7 +1825,7 @@ Damit Sie beim nächsten Aufladen Ihrer Brieftasche keine erhöhte Provision zahlen, soll der Betrag um %s XTZ reduziert werden Wenn der Yield-Modus aktiviert ist, gehen alle zukünftigen Einzahlungen an diese Adresse an Aave. Du kannst über Dein Guthaben weiterhin frei verfügen. Deine %s wird an Aave übermittelt - Die Bereitstellung von %1$s %2$s für Aave steht aus + Die Lieferung von %1$s %2$s an Aave steht noch aus. Genehmigen Die Genehmigung Deines Tokens wurde widerrufen. Erteilen diese erneut, um die Servicefunktionalität fortzusetzen. Genehmigung erforderlich @@ -1689,14 +1835,14 @@ Deine Gelder werden derzeit dem Aave-Protokoll bereitgestellt, Du kannst sie jedoch jederzeit verwalten. Deine%s ist in Aave hinterlegt Chart konnte nicht geladen werden... - Der erhaltene Betrag %1$s %2$s wurde nicht auf Aave eingezahlt. + Das Bereitstellen von %1$s %2$s bei Aave steht aus. APY %1$s%% Verfügbar Aktueller effektiver Jahreszins Beim Aufladen zum Ausleihen wird eine Netzwerkgebühr von maximal %1$s vom Guthaben abgezogen. - Die Netzwerkgebühr ist derzeit zu hoch, um die Kreditvergabe durchzuführen. Die Mittel werden bereitgestellt, sobald sie auf %1$s oder darunter fallen. + Die Netzwerkgebühr ist derzeit zu hoch für die Kreditvergabe. Die Auszahlung erfolgt, sobald sie auf %1$s oder darunter sinkt. Meine Mittel - Dein %1$s ist nun bei Aave hinterlegt und bringt Zinsen ein. Du besitzt einen %2$s-Token, der Dein Guthaben repräsentiert und mit der Zeit wächst. Wenn Du mehr Geld einzahlst, wird dieses an Aave weitergeleitet, um Zinsen abzüglich einer Transaktionsgebühr zu erwirtschaften. + Deine %1$s sind nun bei Aave angelegt und erwirtschaften Rendite. Du besitzt %2$s -Token, die Dein Guthaben repräsentieren und automatisch Rendite generieren. Bei jeder Aufladung wird Dein Aave-Konto zusätzliches Guthaben gutgeschrieben, um weitere Rendite zu erzielen (abzüglich Gebühren). Ertragsmodus Gesamtverdienst Übertragungen zu Aave @@ -1704,16 +1850,16 @@ Dies ist die aktuelle Liefergebühr auf %s. Die tatsächlichen Kosten werden auf der Registerkarte \"Aktivierung\" angezeigt. Aktuelle Gebühr Alle zukünftigen %s-Einzahlungen werden automatisch an Aave geliefert, wobei die Transaktionsgebühr abgezogen wird. - Bei jeder zukünftigen Aufladung wird eine Netzwerkgebühr von ungefähr %1$s (%2$s) abgezogen, die Ihr Limit von %3$s (%4$s) nicht überschreitet. + Von jeder zukünftigen Aufladung wird eine ungefähre Netzwerkgebühr von %1$s ( %2$s ) abgezogen, die Dein Limit von %3$s ( %4$s ) nicht überschreiten wird. Wenn die Netzwerkgebühren über die maximale Gebühr steigen, wird die Transaktion erst durchgeführt, wenn diese sinken. Du kannst dieses Limit später ändern. Maximale Gebühr - Der Mindestbetrag wird aus der aktuellen Netzwerkgebühr berechnet, um sicherzustellen, dass er 4%% nicht überschreitet, was den Mindestbetrag %1$s (%2$s) ergibt. + Der Mindestbetrag wird auf Grundlage der aktuellen Netzwerkgebühr berechnet, sodass er 4%% des Aufladebetrags nicht überschreitet, was einen Mindestbetrag von %1$s (%2$s) ergibt. Mindestaufladung Gebührenpolitik Tangem erhebt außerdem eine Servicegebühr von 15% auf den erzielten Ertrag. Deine Gelder werden automatisch an Aave überwiesen, sobald die Netzwerkgebühren niedriger sind oder Dein Guthaben den erforderlichen Mindestbetrag erreicht. Historische Renditen - Die Freigabe für Deine Token im Yield-Modus wurde widerrufen. Öffne den Token, um die Berechtigung erneut zu erteilen. + Die Genehmigung für Deine Token im Yield-Modus wurde widerrufen. Öffne den Token, um die Berechtigung erneut zu erteilen. Token-Genehmigung erforderlich Prüfe Deine Netzwerkverbindung Informationen zu den Netzwerkgebühren nicht erreichbar @@ -1722,7 +1868,7 @@ Senden, tauschen oder verkaufen Deine Gelder sofort, wann immer Du willst. Jederzeit Zugriff auf Dein Geld Wie funktioniert das? - Aave ist ein dezentrales Protokoll, das einen Gesamtwert von über 61 Milliarden US-Dollar verwaltet. + Aave ist ein dezentrales Protokoll, das ein Gesamtvermögen von über 61 Milliarden Dollar verwaltet. Dezentral und selbstverwahrend Durch die Nutzung dieses Dienstes erklärst Du Dich mit provider\n%1$s und %2$s einverstanden Mit Aave verbinden @@ -1734,24 +1880,28 @@ Unterstützt durch Der Zinssatz ist variabel Wenn Du dein Guthaben auflädst, wird es automatisch an Aave weitergeleitet, um Zinsen zu verdienen. zur Deckung der Transaktionsgebühr wird ein Betrag von %s abgezogen. - Beginn des Verdienstes + Vermögenswerte liefern Dein %s wird an Aave übermittelt, bleibt aber verwaltbar. Siehe Gebührenrichtlinie Deine nächste Aufladung wird automatisch an Aave weitergeleitet. Aktiv Pausiert Deaktiviere den Yield-Modus - Wenn Du diese Option deaktivierst, wird Dein Geld von Aave auf %s in Deiner Wallet abgehoben und es werden keine Belohnungen mehr verdient. + Wenn Du diese Option deaktivierst, werden Deine Vermögenswerte von Aave abgezogen, in Deiner Wallet wieder in %s umgewandelt und die Zinsgutschrift gestoppt. Die Netzwerkgebühr wird von dem Betrag, den Du abhebst, abgezogen. + Deaktiviere den Yield-Modus + Angebot Effektiver Jahreszins für Versorgung Effektiver Jahreszins + Die Zinsen fallen automatisch an. Zinsen fallen automatisch an Ertragsmodus Bearbeitung Deiner Einzahlung + Ertragsmodus Automatisch Einzahlung von %1$s %2$s zur Deckung der Netzwerkgebühr für Transaktionen Die Gebühr %s kann nicht gedeckt werden - Der Stakingservice ist derzeit nicht verfügbar. Bitte versuche es später erneut. - Einnahmen nicht verfügbar + Der Yield-Modus ist momentan nicht verfügbar. Bitte versuche es später erneut. + Ausweichmodus nicht verfügbar Chart konnte nicht geladen werden... diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml index a9f9168d50..558a2135a6 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -396,6 +396,7 @@ Proveedor Mejor tarifa Lista de advertencias de la FCA + Mejor opción Proveedor en la lista de advertencias de la FCA Disponible hasta %s Disponible desde %s @@ -780,6 +781,7 @@ Por saldo Organizar tokens Desagrupar + Soporte de %s Más información Puede activar las Notificaciones para Tangem en Ajustes. Activar más tarde @@ -973,6 +975,7 @@ Esto eliminará la wallet de la aplicación. La wallet en sí puede\nañadirse de nuevo. Nombre Haga que su token trabaje para Ud. + Para comenzar a hacer staking, debe activar su cuenta TON con una auto-transacción de 1 TON. Los fondos permanecerán en su billetera; este paso solo es necesario para habilitar su cuenta para staking. La cantidad del staking debe ser al menos %s La cantidad de staking se redondeará a %1$s TRX debido a las reglas de la red. La cantidad de unstaking se redondeará a %1$s TRX debido a las reglas de la red. @@ -1037,6 +1040,7 @@ Reinvierta las recompensas obtenidas en el monto apostado, aumentando las ganancias potenciales. La opción de volver a staking le permite mover sus fondos de un validador a otro sin necesidad de retirarlos. Está a punto de hacer staking con todo su saldo. Recomendamos dejar una pequeña cantidad para cubrir las tarifas de red para hacer unstaking o reclamar recompensas. + Para empezar a hacer staking, primero debes activar tu cuenta de TON. Para empezar a hacer staking en TON, realice primero una transacción de salida de cualquier importe - esto activará su billetera. Es posible que se requieran hasta 0.2 TON además de la tarifa de red para completar la transacción. Cualquier cantidad no utilizada será reembolsada. Se requieren 0.2 TON para realizar esta operación, además de la tarifa de red. Por favor, recargue su saldo. @@ -1490,7 +1494,7 @@ Sus fondos se suministran actualmente al protocolo Aave, pero puede gestionarlos en cualquier momento. Su %s está depositado en Aave No se puede cargar el gráfico... - La cantidad recibida, %1$s %2$s no fue suministrada a Aave. + El suministro de %1$s %2$s a Aave está pendiente. APY %1$s%% Disponible APY actual @@ -1508,7 +1512,7 @@ Se deducirá una comisión de red aproximada de %1$s (%2$s) de cada recarga futura, y no superará su límite de %3$s (%4$s). Si las tarifas de red superan la tarifa máxima, la transacción no se realizará hasta que disminuyan. Puede cambiar este límite más adelante. Tarifa máxima - El monto mínimo se calcula a partir de la tarifa de red actual para garantizar que no exceda 4%%, lo que hace que el mínimo sea %1$s (%2$s). + El monto mínimo se calcula en función de la comisión de la red actual para que no supere el 4%% del importe de la recarga, lo que hace que el mínimo sea %1$s (%2$s). Recarga mínima Política de tarifas Tangem también cobra una comisión de servicio del 15% sobre el rendimiento obtenido. @@ -1541,14 +1545,17 @@ Sus próximas recargas se suministrarán automáticamente a Aave. Activo En pausa - Desactivar el modo de rendimiento + Desactivación del modo de rendimiento Al desactivar esto, retirará sus fondos de Aave a %s en su billetera y dejará de ganar recompensas. La comisión de red se deducirá del importe que retire. + Desactivar el modo de rendimiento Suministro APY APY + Los intereses se devengan automáticamente Los intereses se devengan automáticamente Modo de rendimiento Procesando su depósito + Modo Rendimiento Automático Deposite algo de %1$s %2$s para cubrir la tarifa de red para las transacciones No se puede cubrir la tarifa %s diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index ef9f1f5500..778dc97f1b 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -372,6 +372,7 @@ Fournisseur Meilleur taux Liste d’avertissement de la FCA + Meilleur choix Disponible jusqu\'à %s Disponible à partir de %s Indisponible pour cette paire @@ -753,6 +754,7 @@ Par solde Organiser les jetons Dégrouper + Assistance %s Plus d\'infos Vous pouvez activer les notifications pour Tangem dans les paramètres. Activer plus tard @@ -1011,6 +1013,7 @@ Réinvestissez vos récompenses gagnées dans le montant que vous avez staké, augmentant ainsi vos gains potentiels. L\'option de restaker vous permet de déplacer vos fonds d\'un validateur à un autre sans avoir besoin de les déstaker. Vous êtes sur le point de staker l\'intégralité de votre solde. Nous vous recommandons de laisser un petit montant pour couvrir les frais de réseau pour unstaking ou la réclamation des récompenses. + Pour commencer le staking, vous devez d’abord activer votre compte TON Pour commencer à staker TON, effectuez d\'abord une transaction sortante de n\'importe quel montant — cela activera votre portefeuille. Jusqu\'à 0,2 TON peuvent être requis en plus des frais de réseau pour terminer la transaction. Tout montant non utilisé sera remboursé. 0,2 TON requis pour effectuer cette opération, en plus des frais de réseau. Veuillez recharger votre solde. @@ -1469,7 +1472,7 @@ Vos fonds sont actuellement affectés au protocole Aave, mais vous pouvez les gérer à tout moment. Vos %s sont déposés dans Aave. Impossible de charger le graphique... - Le montant reçu, %1$s %2$s, n\'a pas été fourni à Aave. + L’approvisionnement de %1$s %2$s sur Aave est en attente. APY %1$s%% Disponible APY actuel @@ -1487,7 +1490,7 @@ Des frais de réseau d\'environ %1$s (%2$s) seront déduits de chaque recharge future, sans dépasser votre limite de %3$s (%4$s). Si les frais de réseau dépassent le montant maximal, la transaction ne sera pas effectuée tant qu\'ils n\'auront pas diminué. Vous pouvez modifier cette limite ultérieurement. Frais maximaux - Le montant minimum est calculé à partir des frais de réseau actuels afin de garantir qu\'il ne dépasse pas 4 %%, ce qui donne un minimum de %1$s (%2$s). + Le montant minimum est calculé en fonction des frais réseau actuels afin de ne pas dépasser 4%% du montant du rechargement, ce qui donne un minimum de %1$s (%2$s). Recharge minimale Politique tarifaire Tangem prélève également des frais de service de 15% sur les revenus générés. @@ -1520,9 +1523,10 @@ Vos prochains dépôts seront automatiquement transférés vers Aave. Actif En pause - Désactiver le mode rendement + Désactivation du mode de rendement En désactivant cela, vos fonds seront retirés d\'Aave vers %s dans votre portefeuille et vous ne gagnerez plus de récompenses. Les frais de réseau seront déduits du montant que vous retirez. + Désactiver le mode rendement Rendement annuel brut (APY) APY Les intérêts sont cumulés automatiquement. diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 2d8b7ca984..74b96d49b9 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -30,6 +30,7 @@ アカウントをアーカイブする アーカイブ このアカウントをアーカイブしますが、いつでも復元できます。 + アーカイブ中・・・ アカウント アカウントが保存されました 報酬用のアカウント @@ -156,6 +157,13 @@ %1$dトークン + 続行するには次のデバイスをリセットしてください。 + ウォレットのリセット + すべてのTangemデバイスがリセットされました。ウォレットのアップグレードを続行できます。 + もう一度アップグレードしてください + リセット完了 + すべてのTangemデバイスをリセットしていません + すべてのTangemデバイスをリセットしていません このカードを使用して、このウォレット内の他のカードまたはリングのアクセスコードをリセットしたくない場合は、このオプションを無効にしてください。これにより、このカードのアクセスコードもリセットできなくなりますのでご注意ください。 このカードを使用して、このウォレット内の他のカードのアクセスコードをリセットできます。 アクセスコードの復元 @@ -307,6 +315,7 @@ リロード 名前を変更 必須 + リセット 保存 変更内容を保存 検索 @@ -423,6 +432,7 @@ WalletConnectエラー 別のウォレットのカードまたはリングを使用しました。このウォレットにリンクしているカードまたはリングをタップしてください。 取引に必要な資金が不足しています。アカウントに入金してください。 + ポートフォリオ内のアセットをこのトークンと交換します マイトークン まだトークンを追加していません。マーケットからトークンを追加して交換してください。 %sとの交換はできません @@ -478,7 +488,7 @@ プロバイダー ベストレート FCA警告リスト - ベストチョイス + 最適な選択 FCA警告リストに掲載されたプロバイダー 最大 %s まで使用可能 %s 以上で利用可能 @@ -521,6 +531,13 @@ 続行するには、%1sスマートコントラクトに%2sを使用する権限を付与してください 許可を与える 無制限 + バックアップは2枚または3枚のTangemカードを使って作成されます。紛失や破損に備えて、それぞれ別々の安全な場所に保管してください—シードフレーズは不要です。 + 複数のカードでバックアップ + Tangemウォレットを追加 + あなたの秘密鍵はTangemカード内部で直接生成され、決してカードの外に出ることはありません。 + 鍵生成 + すべての暗号処理は、複製や物理的な改ざんに対する認証を受けたセキュアチップ内で行われます。 + ハードウェアレベルのセキュリティ 既存のウォレットを追加 新しいウォレットを作成する Tangemを注文 @@ -559,6 +576,21 @@ 既存のウォレットをインポートする このリカバリーフレーズはすでにインポートされています。 モバイルウォレット + ウォレット削除 + このウォレットはデバイスから完全に削除されます。 + 本当にこれを実行しますか? + ウォレット削除 + バックアップへ移動 + バックアップを表示 + ウォレット削除 + とにかく削除する + このウォレットにはバックアップが存在します。後で復元できるように、削除する前に内容を確認してください。 + バックアップなしでこのウォレットを削除すると、資金へのアクセスを永久に失います。 + このウォレットを削除しますか? + ウォレットの削除前にバックアップをしていなければ、アクセスを失う可能性があることを理解しています。 + ウォレットを削除しても中身自体が消えるわけではなく、単にこのデバイスから表示が消えるだけであることを理解しています。 + もはやシードフレーズは不要——Tangemカードやリングがそのままあなたの安全なバックアップになります。 + Tangemでバックアップ アップグレードできません。このデバイスにはすでにウォレットが存在します。 別のデバイスを選択してください。このデバイスはアップグレードに使用できません。 操作中にエラーが発生しました。 @@ -779,6 +811,8 @@ 暗号資産を買い付ける SEPA送金で暗号資産を買い付けると、**手数料 0% ** になります。 SEPAで暗号資産を購入 + 事前申し込み受付中。他にない特別なカードを、いち早く体験しよう。 + Tangem Visaカード すべてのデバイスを保護するには、単一のアクセスコードを設定してください。 保護する 後で各カードおよびリングに個別のアクセスコードを設定できます。 @@ -1191,7 +1225,7 @@ 獲得した報酬をステーキングに再投資し、潜在的な収益を増やします。 再ステーキングを使うと、ステーキングを解除することなく、あるバリデータから別のバリデータに資金を移動できます。 ウォレットの残高をすべてステーキングすると、ステーキング解除時にネットワーク手数料の支払いが必要になります。そのため、少額をウォレットに残しておくことをおすすめします。 - ステーキングを始めるには、TONアカウントを1 TONの自己取引で有効化する必要があります。資金はウォレット内にそのまま残り、この手順でステーキング用にアカウントを有効化できます。 + ステーキングを開始するには、まずTONアカウントを有効化してください。 アカウントの有効化 TONのステーキングを開始するには、まず自分のアドレスに少額の取引を送信します。これによりウォレットが有効になります。 取引を完了するには、ネットワーク手数料に加えて最大0.2TONが必要になる場合があります。未使用分は返金されます。 @@ -1303,21 +1337,38 @@ 取引を表示 サービス手数料 手数料 + カードを紛失したり盗まれたりしても、資金を安全に保てます。一時停止はいつでも解除できます。 + カードを一時停止しますか? + 一時停止 + サポートを受ける 完了 拒否 保留中 銀行がこの取引リクエストを拒否しました。 この手数料は、送金処理にかかるコストをカバーするためのものです。 出金 + 資金を追加 + 入金オプション PINを変更する カードは支払いの準備が整いました。 PINコードを作成しました データの読み込みに失敗しました。しばらくしてからもう一度お試しください。 カードの一時停止 非表示 + Googleウォレットを開く + 数回タップするだけでTangem Payの設定完了。Google Payですぐに支払いを始めましょう。 + Google Payにカードを追加する + Googleウォレットを開く + 「カードを追加」をタップします + カードの詳細を手動で入力してください + お使いの端末に送信されたワンタイムパスワード(OTP)でカードを認証してください。 + 準備完了!カードはすぐに使用できます。 + Google Payにカードを追加する + アドレスを共有するか、QRコードを表示してください。 技術的な問題が検出されました。しばらくしてからもう一度お試しいただくか、サポートにお問い合わせください。 現在、受け取りは利用できません 表示 + ポートフォリオ内のあらゆる資産をカードと交換 カードの詳細 アカウントを作成してカードを発行 Tangem Pay @@ -1754,7 +1805,7 @@ あなたの資金は現在Aaveプロトコルに預けられていますが、いつでも自由に管理できます。 あなたの%sはAaveに預けられています チャートを読み込めません・・ - 受け取った金額%1$s %2$sはAaveに入金されませんでした。 + Aaveへの%1$s %2$sの供給は保留中です。 年利%1$s%% 利用可能 現在のAPY @@ -1772,7 +1823,7 @@ 今後のチャージごとに、おおよそ%1$s(%2$s)のネットワーク手数料が差し引かれますが、上限の%3$s(%4$s)を超えることはありません。 ネットワーク手数料が上限手数料を超えた場合、手数料が下がるまで取引は成立しません。この制限は後で変更できます。 最大手数料 - 最小金額は現在のネットワーク手数料に基づいて計算されており、手数料が4%を超えないように設定されています。そのため、最小金額は%1$s(%2$s)となります。 + 最小金額は、ネットワーク手数料がチャージ額の4%を超えないように現在の手数料に基づいて計算されます。その結果、最小金額は%1$s(%2$s)となります。 最低入金額 手数料ポリシー Tangemはまた、得られた利回りに対して15%のサービス手数料を差し引きます。 @@ -1808,10 +1859,11 @@ 利回りモードを無効にする これをオフにすると、Aaveから資産が引き出され、ウォレット内の%sに変換され、利回りの発生が停止します。 出金金額からネットワーク手数料が差し引かれます。 + 利回りモードを無効にする 供給 供給APY APY - 利息は自動的に発生します + 利息は自動的に発生します。 利息は自動的に発生します 利回りモード 入金の処理中 diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 393f0891ea..7e27e29ccb 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -5,6 +5,7 @@ Невозможно восстановить аккаунт Архив Вы архивируете свой аккаунт, но в любое время можете вернуть его обратно + Архивация... Имя аккаунта уже существует Аккаунт Новый аккаунт @@ -96,6 +97,9 @@ %d устройств %d устройств + Пожалуйста, сбросьте следующее устройство, чтобы продолжить. + Сброс кошелька + Сброс завершен Отключите эту опцию, если не хотите, чтобы эта карта использовалась для сброса кодов доступа на другие карты этого кошелька. Обратите внимание, сброс кода также не будет доступен на этой карте. Использовать эту карту для сброса кода доступа на других картах в этом кошельке Восстановление доступа @@ -121,6 +125,7 @@ Недостаточно ADA Принять Доступ запрещен + Аккаунт Активировать Добавить Добавить в портфель @@ -232,6 +237,7 @@ Отклонить Перезагрузить Переименовать + Сброс Сохранить Сохранить изменения Поиск @@ -856,6 +862,7 @@ По балансу Упорядочить токены Список + Поддержка %s Подробнее Вы можете включить нотификации в настройках Включить позже @@ -1117,7 +1124,7 @@ Реинвестируйте свои заработанные награды в вашу застейканную сумму, увеличивая потенциальный доход Рестейк позволяет вам переместить средства из одного валидатора в другого без необходимости выхода из стейкинга. Вы собираетесь застейкать весь баланс, рекомендуем оставить небольшую сумму для оплаты комиссии сети при выходе из стейкинга или получении награды. - Чтобы начать стейкинг, ваш TON-аккаунт должен быть активирован транзакцией самому себе на 1 TON. Средства остаются в вашем кошельке — этот шаг лишь активирует ваш аккаунт для участия в стейкинге. + Чтобы начать стейкинг, сначала активируйте свой TON-аккаунт. Активация аккаунта Чтобы начать стейкинг в TON, сначала отправьте небольшую транзакцию на свой же адрес — это активирует ваш кошелёк. До 0.2 TON может потребоваться сверх сетевой комиссии для завершения транзакции. Неиспользованная часть будет возвращена. @@ -1312,6 +1319,7 @@ Разблокировать все Разблокировать все с %s ПИН не принят. Попробуйте ещё раз или введите другой код. + Что выбрать? Блокчейн недоступен. Попробуйте позже. Отсканируйте карту или кольцо Этот кошелек уже был активирован ранее.\nЕсли это сделали не вы, свяжитесь со службой поддержки.\nTangem никогда не продает кошелек вместе с предустановленным кодом доступа. @@ -1577,6 +1585,7 @@ Чтобы не платить повышенную комиссию при следующем пополнении кошелька, уменьшите сумму на %s XTZ При активном режиме доходности все будущие депозиты на этот адрес будут направляться в Aave. Вы по-прежнему можете свободно управлять своими средствами. Ваш %s внесён в Aave + Отправка %1$s %2$s в Aave находится в ожидании Выдать разрешение Разрешение для вашего токена было отозвано. Выдайте его снова, чтобы продолжить работу сервиса. Необходимо разрешение @@ -1586,21 +1595,25 @@ Ваши средства в данный момент размещены в протоколе Aave, но вы можете воспользоваться ими в любое время. Ваш %s внесён в Aave Невозможно загрузить график - Полученная сумма, %1$s %2$s, не была зачислена на Aave. + Отправка %1$s %2$s на Aave ожидает выполнения. APY %1$s%% Доступно Текущий APY + При пополнении в режиме доходности с баланса будет удержана комиссия сети, не превышающая %1$s. + Сейчас комиссия сети слишком высока для выполнения операции. Средства будут отправлены, как только она снизится до %1$s или ниже. Мои средства Ваши %1$s теперь внесён в Aave и приносит проценты. У вас есть токен %2$s, который отражает ваш баланс и со временем увеличивается. При пополнении средства автоматически направляются в Aave для получения процентов за вычетом комиссии за транзакцию. + Режим доходности Итоговый доход Переводы в Aave Изучите Aave Это текущая комиссия в сети %s. Текущая комиссия Все следующие пополнения %s автоматически поступят в Aave с удержанием комиссии за транзакцию. + Примерная комиссия сети в размере %1$s (%2$s) будет удерживаться с каждого будущего пополнения и не превысит ваш лимит %3$s (%4$s). Если комиссия сети превысит максимальный лимит, транзакция не будет выполнена до тех пор, пока комиссия не снизится. Вы сможете изменить этот лимит позже. Максимальная комиссия - Это минимальный депозит, который можно отправить в Aave. Чтобы депозиты оставались прибыльными, мы не обрабатываем их, когда комиссия сети превышает %1$s%2$sот суммы. + Минимальная сумма рассчитывается исходя из текущей комиссии сети, чтобы она не превышала 4%% от суммы пополнения, что составляет минимум %1$s (%2$s). Минимальный депозит Политика комиссий Tangem взимает комиссию за обслуживание в размере 15% от полученного дохода. @@ -1615,11 +1628,11 @@ Отправляйте, обменивайте или продавайте свои средства мгновенно, когда захотите. Мгновенный вывод средств Как это работает? - Aave — это децентрализованный протокол, управляющий активами на сумму более 61 миллиарда долларов США. + Aave — децентрализованный протокол, управляющий активами на сумму более $61 млрд. Децентрализованный и некастодиальный Используя сервис, вы соглашаетесь с условиями провайдера %1$s и %2$s Подключить Aave - Aave %1$s%%• Ставка с плавающим процентом + Aave %1$s%% • Плавающая ставка Aave Сред. %s Доходность за прошлый год @@ -1633,14 +1646,18 @@ Следующие пополнения вашего счёта автоматически поступят в Aave. Активен На паузе - Завершить заработок + Завершение режима доходности Выключив эту функцию, вы выведёте средства из Aave, получите их обратно в %s в своем кошельке и перестанете зарабатывать награды. Комиссия сети будет вычтена из суммы вашего вывода. + Завершить режим доходности + Внесение Годовая доходность (APY) APY + Проценты начисляются автоматически. Проценты начисляются автоматически. Режим доходности Отправка ваших средств + Режим доходности Автоматически Внесите немного %1$s %2$s, чтобы покрыть комиссию сети за транзакции. Невозможно покрыть комиссию в %s diff --git a/core/res/src/main/res/values-uk-rUA/strings.xml b/core/res/src/main/res/values-uk-rUA/strings.xml index 936f193cce..bb34e10eab 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -370,6 +370,7 @@ Провайдер Найкращий курс Список попереджень FCA + Найкращий вибір Доступно до %s Доступно від %s Недоступно для цієї пари @@ -760,6 +761,7 @@ За балансом Сортування токенів Список + Підтримка %s Більше Ви можете ввімкнути сповіщення у налаштуваннях Увімкнути пізніше @@ -1017,6 +1019,7 @@ Реінвестуйте зароблені винагороди у суму стейкінгу, щоб збільшити потенційний прибуток. Рестейк дозволяє вам перемістити ваші кошти від одного валідатора до іншого без необхідності виводити кошти зі стейкінгу Ви збираєтеся застейкати весь свій баланс. Ми рекомендуємо залишити невелику суму, щоб покрити комісію мережі за зняття коштів або отримання винагороди. + Щоб розпочати стейкінг, спочатку активуйте свій TON-акаунт. Щоб почати стейкінг в TON, спочатку здійсніть вихідну транзакцію на будь-яку суму — це активує ваш гаманець. До 0.2 TON може знадобитися додатково мережевої комісії для завершення транзакції. Невикористана частина буде повернута. Для виконання операції потребується додатково 0.2 TON, крім мережевої комісії. Будь ласка, поповніть баланс. @@ -1446,7 +1449,7 @@ Наразі ваші кошти розміщені у протоколі Aave, але ви можете керувати ними в будь-який час. Ваш %s внесений у Aave Неможливо завантажити графік - Отримана сума, %1$s %2$s не була зарахована на Aave. + Поповнення %1$s %2$s на Aave очікує виконання. APY %1$s%% Доступно Поточний APY @@ -1464,7 +1467,7 @@ Приблизна мережева плата в розмірі %1$s (%2$s) буде вираховуватися з кожного наступного поповнення, і вона не перевищуватиме ваш ліміт %3$s (%4$s). Якщо мережеві комісії перевищують максимальну комісію, транзакція не пройде, поки вони не знизяться. Ви можете змінити цей ліміт пізніше. Максимальна комісія - Це найменший депозит, який можна надіслати в Aave. Щоб депозити залишалися прибутковими, ми не обробляємо їх, коли комісія мережі перевищує %1$s%2$s від суми. + Мінімальна сума розраховується з урахуванням поточного збору мережі, щоб вона не перевищувала 4%%, що становить мінімум %1$s (%2$s). Мінімальне поповнення Політика комісій Tangem комісію за обслуговування у розмірі 15% від отриманого доходу. @@ -1479,11 +1482,11 @@ Відправляйте, обмінюйте або продавайте свої кошти миттєво, в будь-який час. Миттєвий вивід коштів Як це працює? - Aave — це децентралізований протокол, який управляє активами загальною вартістю понад 61 мільярд доларів. + Aave — децентралізований протокол, що керує активами на понад $61 млрд. Децентралізований та некастодіальний Використовуючи сервіс, ви погоджуєтесь з умовами провайдера %1$s та %2$s Підключити Aave - Aave %1$s%% • Ставка з плаваючим відсотком + Aave %1$s%% • Плаваюча ставка Аave Серед. %s Дохідність за минулий рік @@ -1497,14 +1500,17 @@ Ваші наступні поповнення рахунку автоматично надходитимуть до Aave. Активний На паузі - Завершити заробіток + Вимкнення режиму прибутковості Вимкнення цієї опції виведе ваші активи з Aave, отримаєте їх назад у %s у вашому гаманці і зупинить накопичення нагород. Комісія мережі буде вирахувана з суми, яку ви знімаєте. + Завершити заробіток Річна прибутковість (APY) APY + Відсотки нараховуються автоматично. Відсотки нараховуються автоматично Режим дохідності Відправка ваших коштів + Режим прибутковості Автоматично Внесіть трохи %1$s %2$s, щоб покрити комісію мережі за транзакції. Неможливо покрити комісію в %s diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 143869f7f9..759d5737b1 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -160,6 +160,13 @@ %d token %d tokens + Please reset the next device to continue. + Wallet reset + All Tangem devices have been reset. You can now continue upgrading your wallet. + Upgrade again + Reset complete + You haven’t reset all your Tangem devices + You haven’t reset all your Tangem devices Disable this option if you don\'t want this card to be used to reset access codes on other cards or rings in this wallet. Please note that this will also prevent you from resetting the access code on this card. Allows you to use this card to reset access code on other cards in this wallet Access code recovery @@ -314,6 +321,7 @@ Reload Rename Required + Reset Save Save changes Search @@ -531,6 +539,13 @@ To continue, grant %1s smart contracts permission to use your %2s Give Permission Unlimited + Your backup is created using 2 or 3 Tangem cards. Keep them in separate safe places to protect against loss or damage — no seed phrase needed. + Backup with Multiple Cards + Add Tangem Wallet + Your private key is generated directly inside the Tangem card and never leaves it. + Key Generation + All cryptographic operations happen inside the secure chip, certified against cloning and physical tampering. + Hardware-Level Security Add Existing Wallet Create New Wallet Order Tangem @@ -572,6 +587,21 @@ Import existing wallet This recovery phrase has already been imported Mobile Wallet + Forget wallet + This wallet will be permanently removed from your device + Are you sure you want to do this? + Forget wallet + Go to backup + View backup + Forget wallet + Forget Anyway + A backup for this wallet exists. Review it before forgetting to make sure you can recover later. + If you forget this wallet without a backup, you’ll permanently lose access to your funds. + Forget this wallet? + I understand that if I haven\'t backed up my wallet before removing it, I may lose access to it. + I understand that removing my wallet does not delete it—but simply removes it from my device. + No seed phrase is needed anymore — your Tangem card or ring becomes your secure backup. + Backup with Tangem Can’t upgrade. A wallet already exists on this device. Pick another device. This one can’t be used for the upgrade. An error occurred during the operation. @@ -1150,7 +1180,7 @@ Name Put your token to work A network fee is a small payment required to process and confirm your transaction on the blockchain. - 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. + To begin staking, your TON account must be activated with a transaction of 1 TON. The funds stay in your account because this step only activates it for staking. Account activation The amount to stake must be at least %s Staking amount will be rounded to %1$s TRX due to network rules. @@ -1219,7 +1249,7 @@ 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 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. + To begin staking, you need to activate your TON account first. Account activation To start staking in TON, first send a small transaction to your own address — this will activate your wallet. Up to 0.2 TON may be required in addition to the network fee to complete the transaction. Any unused amount will be refunded. @@ -1331,12 +1361,18 @@ Explore transaction Service fees Fee + Keep your money safe if your card is lost or stolen. You can unfreeze anytime. + Freeze your card? + Freeze + Get Help Completed Declined Pending The bank rejected this transaction request. This fee goes to cover the cost of handling your transfer. Withdrawal + Add funds + Top-up options Change PIN The card is fully ready for payments. PIN code created @@ -1352,9 +1388,11 @@ Verify card using the OTP sent to your device. All set! Your card is ready to use. Add card to Google Pay + Share your address or show QR-code Technical issues detected. Please try again later or contact support. Receive unavailable now Reveal + Swap any asset in your portfolio for card Card details Create account and issue a card Tangem Pay @@ -1840,12 +1878,12 @@ Your funds are currently supplied to the Aave protocol, but you can manage them at any time. Your %s is deposited in Aave Unable to load chart... - The amount received, %1$s %2$s was not supplied to Aave. + Supplying %1$s %2$s to Aave is pending. APY %1$s%% Available Current APY When topping up for lending, a network fee not exceeding %1$s will be deducted from the balance. - The network fee is currently too high to execute lending. Funds will be supplied once it drops to %1$s or below. + The network fee is currently too high to execute lending. Funds will be supplied once it drops to %1$s or below. My funds Your %1$s is now deployed to Aave and earning yield. You hold %2$s tokens, which represent your balance and accrue yield automatically. When you top up, funds are added to Aave to earn more yield, minus fees. Yield mode @@ -1858,7 +1896,7 @@ An approximate network fee of %1$s (%2$s) will be deducted from each future top-up, and it won’t exceed your %3$s (%4$s) limit. 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 minimum amount is calculated from the current network fee to ensure it does not exceed 4%%, which makes the minimum %1$s (%2$s). + The minimum amount is calculated based on the current network fee so that it does not exceed 4%% of the top-up amount, which makes the minimum %1$s (%2$s). Minimum top-up Fee policy Tangem also takes a 15% service fee on yield earned. @@ -1891,13 +1929,14 @@ Your next top-ups will be automatically supplied to Aave. Active Paused - Disable yield mode + Disabling Yield Mode Turning this off will withdraw your assets from Aave, convert them back to %s in your wallet, and stop yield accrual. The network fee will be deducted from the amount you withdraw. + Disable yield mode Supply Supply APY APY - Interest accrues automatically + Interest accrues automatically. Interest accrues automatically Yield mode Processing your deposit diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/label/Label.kt b/core/ui/src/main/java/com/tangem/core/ui/components/label/Label.kt index 860dba2c51..951e6a5042 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/label/Label.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/label/Label.kt @@ -75,6 +75,7 @@ fun Label(state: LabelUM, modifier: Modifier = Modifier) { .padding(horizontal = 8.dp, vertical = 4.dp), ) { Text( + modifier = Modifier.weight(1.0f, fill = false), text = text.resolveReference(), style = TangemTheme.typography.caption1, color = textColor, @@ -125,7 +126,9 @@ private fun LabelPreview() { ) Label( state = LabelUM( - text = TextReference.Str("Regular Label"), + text = TextReference.Str( + "Regular long long long long long long long long long long long long Label", + ), style = LabelStyle.REGULAR, icon = R.drawable.ic_information_24, ), diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetMaxFeeUseCase.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetMaxFeeUseCase.kt index 127029c78c..60a316b9f7 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetMaxFeeUseCase.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetMaxFeeUseCase.kt @@ -14,11 +14,15 @@ import java.math.BigDecimal import java.math.RoundingMode /** - * Calculates max allowed network fee for Yield Supply enter transaction expressed in token units. + * Calculates the max allowed network fee for a Yield Supply transaction. * - * Uses YieldMarketToken.maxFeeNative (native coin units) and converts it to token units with the - * same conversion logic as [YieldSupplyGetCurrentFeeUseCase]: based on fiat rate ratio - * (nativeFiatRate / tokenFiatRate). + * Result is a Pair where: + * - first: fee in native coin units (maxFeeNative) + * - second: the same fee converted to token units using the fiat-rate ratio + * (nativeFiatRate / tokenFiatRate). + * + * Uses YieldMarketToken.maxFeeNative and the same conversion logic as + * [YieldSupplyGetCurrentFeeUseCase]. */ class YieldSupplyGetMaxFeeUseCase( private val yieldSupplyRepository: YieldSupplyRepository, @@ -29,7 +33,7 @@ class YieldSupplyGetMaxFeeUseCase( suspend operator fun invoke( userWallet: UserWallet, cryptoCurrencyStatus: CryptoCurrencyStatus, - ): Either = catch { + ): Either> = catch { val token = cryptoCurrencyStatus.currency as? CryptoCurrency.Token ?: error("CryptoCurrency must be token for max fee calculation") @@ -65,6 +69,6 @@ class YieldSupplyGetMaxFeeUseCase( val tokenValue = rateRatio.multiply(maxFeeNative) - tokenValue.stripTrailingZeros() + maxFeeNative to tokenValue.stripTrailingZeros() } } \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/entity/YieldSupplyFeeUM.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/entity/YieldSupplyFeeUM.kt index 7b3d8e94ed..ccc975f7ff 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/entity/YieldSupplyFeeUM.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/entity/YieldSupplyFeeUM.kt @@ -5,7 +5,6 @@ import com.tangem.blockchain.common.TransactionData import com.tangem.core.ui.components.currency.icon.CurrencyIconState import com.tangem.core.ui.extensions.TextReference import kotlinx.collections.immutable.ImmutableList -import java.math.BigDecimal @Immutable internal sealed class YieldSupplyFeeUM { @@ -31,5 +30,4 @@ internal data class YieldSupplyActionUM( val yieldSupplyFeeUM: YieldSupplyFeeUM, val isPrimaryButtonEnabled: Boolean, val isTransactionSending: Boolean, - val maxFee: BigDecimal = BigDecimal.ZERO, ) \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/ui/YieldSupplyBlockContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/ui/YieldSupplyBlockContent.kt index 2e90010033..1cbf8f1cfe 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/ui/YieldSupplyBlockContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/ui/YieldSupplyBlockContent.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider @@ -91,6 +92,7 @@ private fun SupplyUnavailable(modifier: Modifier = Modifier) { ) } +@Suppress("LongMethod") @Composable private fun SupplyContent(supplyUM: YieldSupplyUM.Content, modifier: Modifier = Modifier) { Row( @@ -115,8 +117,11 @@ private fun SupplyContent(supplyUM: YieldSupplyUM.Content, modifier: Modifier = horizontalArrangement = Arrangement.spacedBy(4.dp), ) { Text( + modifier = Modifier.weight(1.0f, fill = false), text = supplyUM.title.resolveReference(), style = TangemTheme.typography.subtitle1, + maxLines = 1, + overflow = TextOverflow.Ellipsis, color = TangemTheme.colors.text.primary1, ) AnimatedVisibility(supplyUM.rewardsApy != TextReference.EMPTY) { @@ -344,17 +349,17 @@ private class PreviewProvider : PreviewParameterProvider { onClick = {}, ), YieldSupplyUM.Content( - title = stringReference("Aave lending is active"), + title = stringReference("Aave l"), subtitle = stringReference("Interest accrues automatically"), - rewardsApy = stringReference("5.1 % APY"), + rewardsApy = stringReference("APY 5.1%"), onClick = {}, apy = "5.1", showWarningIcon = false, ), YieldSupplyUM.Content( - title = stringReference("Aave lending is active"), + title = stringReference("Aave lending is active "), subtitle = stringReference("Interest accrues automatically"), - rewardsApy = stringReference("5.1 % APY"), + rewardsApy = stringReference("APY 5.1%"), onClick = {}, apy = "5.1", showWarningIcon = true, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt index 7e864db727..12359bae82 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt @@ -6,6 +6,8 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -30,7 +32,6 @@ import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.impl.promo.entity.YieldSupplyPromoUM import com.tangem.features.yield.supply.impl.promo.model.YieldSupplyPromoClickIntents -@Suppress("MagicNumber") @Composable internal fun YieldSupplyPromoContent( yieldSupplyPromoUM: YieldSupplyPromoUM, @@ -38,50 +39,18 @@ internal fun YieldSupplyPromoContent( modifier: Modifier = Modifier, ) { Column( - horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier .background(color = TangemTheme.colors.background.tertiary) - .fillMaxWidth() + .fillMaxSize() .imePadding() - .systemBarsPadding() - .padding(horizontal = 16.dp), + .systemBarsPadding(), + horizontalAlignment = Alignment.CenterHorizontally, ) { YieldStatusAppBar( onBackClick = clickIntents::onBackClick, onHowItWorksClick = clickIntents::onHowItWorksClick, ) - Column( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.padding(horizontal = 20.dp), - ) { - Icon( - imageVector = ImageVector.vectorResource(R.drawable.ic_analytics_up_24), - tint = TangemTheme.colors.icon.accent, - contentDescription = null, - modifier = Modifier - .background(TangemTheme.colors.icon.accent.copy(0.1f), CircleShape) - .padding(12.dp) - .size(32.dp), - ) - SpacerH(20.dp) - Text( - text = yieldSupplyPromoUM.title.resolveReference(), - style = TangemTheme.typography.h2, - color = TangemTheme.colors.text.primary1, - ) - SpacerH8() - Label( - state = LabelUM( - text = yieldSupplyPromoUM.subtitle, - style = LabelStyle.REGULAR, - icon = R.drawable.ic_information_24, - onIconClick = clickIntents::onApyInfoClick, - ), - ) - SpacerH32() - PromoItems() - } - SpacerHMax() + Content(yieldSupplyPromoUM = yieldSupplyPromoUM, clickIntents = clickIntents) YieldSupplyTosText( tosLink = yieldSupplyPromoUM.tosLink, policyLink = yieldSupplyPromoUM.policyLink, @@ -90,16 +59,72 @@ internal fun YieldSupplyPromoContent( PrimaryButton( text = stringResourceSafe(R.string.yield_module_start_earning), onClick = clickIntents::onStartEarningClick, - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .padding( + start = 16.dp, + end = 16.dp, + bottom = 8.dp, + ) + .fillMaxWidth(), + ) + } +} + +@Suppress("MagicNumber") +@Composable +private fun ColumnScope.Content(yieldSupplyPromoUM: YieldSupplyPromoUM, clickIntents: YieldSupplyPromoClickIntents) { + Box(modifier = Modifier.weight(1f)) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp) + .verticalScroll(rememberScrollState()), + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.padding(horizontal = 20.dp), + ) { + Icon( + imageVector = ImageVector.vectorResource(R.drawable.ic_analytics_up_24), + tint = TangemTheme.colors.icon.accent, + contentDescription = null, + modifier = Modifier + .background(TangemTheme.colors.icon.accent.copy(0.1f), CircleShape) + .padding(12.dp) + .size(32.dp), + ) + SpacerH(20.dp) + Text( + text = yieldSupplyPromoUM.title.resolveReference(), + style = TangemTheme.typography.h2, + color = TangemTheme.colors.text.primary1, + ) + SpacerH8() + Label( + state = LabelUM( + text = yieldSupplyPromoUM.subtitle, + style = LabelStyle.REGULAR, + icon = R.drawable.ic_information_24, + onIconClick = clickIntents::onApyInfoClick, + ), + ) + SpacerH32() + PromoItems() + } + SpacerH32() + } + Fade( + backgroundColor = TangemTheme.colors.background.tertiary, + modifier = Modifier.align(Alignment.BottomCenter), ) - SpacerH8() } } @Composable private fun YieldStatusAppBar(onBackClick: () -> Unit, onHowItWorksClick: () -> Unit) { Row( - modifier = Modifier.padding(vertical = 16.dp), + modifier = Modifier.padding(16.dp), verticalAlignment = Alignment.CenterVertically, ) { Icon( @@ -165,7 +190,12 @@ private fun PromoItem(@DrawableRes icon: Int, title: TextReference, subtitle: Te } @Composable -private fun YieldSupplyTosText(tosLink: String, policyLink: String, onClick: (String) -> Unit) { +private fun YieldSupplyTosText( + tosLink: String, + policyLink: String, + onClick: (String) -> Unit, + modifier: Modifier = Modifier, +) { val tosTitle = stringResourceSafe(R.string.common_terms_of_use) val policyTitle = stringResourceSafe(R.string.common_privacy_policy) val fullString = stringResourceSafe(id = R.string.yield_module_promo_screen_terms_disclaimer, tosTitle, policyTitle) @@ -204,7 +234,7 @@ private fun YieldSupplyTosText(tosLink: String, policyLink: String, onClick: (St textAlign = TextAlign.Center, style = TangemTheme.typography.caption2, color = TangemTheme.colors.text.tertiary, - modifier = Modifier + modifier = modifier .fillMaxWidth() .padding(16.dp), ) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt index 070ec52cb7..bfb21a8ec9 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt @@ -248,7 +248,7 @@ internal class YieldSupplyActiveModel @Inject constructor( cryptoCurrencyStatus = cryptoStatus, appCurrency = appCurrency, feeValue = currentFee, - maxNetworkFee = maxFee, + maxNetworkFee = maxFee.second, analyticsHandler = analyticsHandler, ), ) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt index 65cc7f76f0..c9dc6d5b65 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt @@ -13,7 +13,6 @@ import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency -import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase @@ -62,8 +61,8 @@ internal class YieldSupplyStartEarningModel @Inject constructor( private val yieldSupplyNotificationsUpdateTrigger: YieldSupplyNotificationsUpdateTrigger, private val yieldSupplyAlertFactory: YieldSupplyAlertFactory, private val yieldSupplyActivateUseCase: YieldSupplyActivateUseCase, - private val yieldSupplyGetTokenStatusUseCase: YieldSupplyGetTokenStatusUseCase, private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase, + private val yieldSupplyGetMaxFeeUseCase: YieldSupplyGetMaxFeeUseCase, private val yieldSupplyRepository: YieldSupplyRepository, ) : Model(), YieldSupplyNotificationsComponent.ModelCallback { @@ -131,11 +130,8 @@ internal class YieldSupplyStartEarningModel @Inject constructor( } } - private suspend fun getMaxFee(): BigDecimal? { - if (uiState.value.maxFee != BigDecimal.ZERO) return uiState.value.maxFee - val yieldTokenStatus = yieldSupplyGetTokenStatusUseCase(cryptoCurrency as CryptoCurrency.Token) - .getOrNull() - return yieldTokenStatus?.maxFeeNative + private suspend fun getMaxFeePair(): Pair? { + return yieldSupplyGetMaxFeeUseCase(userWallet, cryptoCurrencyStatus).getOrNull() } private suspend fun onLoadFee() { @@ -145,11 +141,10 @@ internal class YieldSupplyStartEarningModel @Inject constructor( it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) } - val maxFee = if (uiState.value.maxFee == BigDecimal.ZERO) { - getMaxFee() - } else { - uiState.value.maxFee - } ?: return + val maxFeePair = getMaxFeePair() ?: return + + val maxFee = maxFeePair.first + val maxFeeFiat = maxFeePair.second val transactionListData = yieldSupplyStartEarningUseCase( userWalletId = userWallet.walletId, @@ -190,6 +185,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( val feeSum = updatedTransactionList.sumOf { it.fee?.amount?.value.orZero() } + uiState.update( YieldSupplyStartEarningFeeContentTransformer( cryptoCurrencyStatus = cryptoCurrencyStatusFlow.value, @@ -198,6 +194,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( updatedTransactionList = updatedTransactionList, feeValue = feeSum, maxNetworkFee = maxFee, + maxNetworkFeeFiat = maxFeeFiat, minAmount = minAmount, ), ) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt index b76fd630a4..189ffa8a23 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt @@ -25,6 +25,7 @@ internal class YieldSupplyStartEarningFeeContentTransformer( private val updatedTransactionList: List, private val feeValue: BigDecimal, private val maxNetworkFee: BigDecimal, + private val maxNetworkFeeFiat: BigDecimal, private val minAmount: BigDecimal, ) : Transformer { override fun transform(prevState: YieldSupplyActionUM): YieldSupplyActionUM { @@ -42,14 +43,8 @@ internal class YieldSupplyStartEarningFeeContentTransformer( val tokenFiatFee = feeFiat // same fiat amount val tokenFiatFeeValueText = tokenFiatFee.format { fiat(appCurrency.code, appCurrency.symbol) } - val maxFiatFee = feeFiatRate?.let { rate -> - maxNetworkFee.multiply(rate) - } - val maxFeeCryptoValueText = tokenFiatRate?.let { rate -> - maxFiatFee?.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) - }.format { crypto(cryptoCurrency) } - - val maxFiatFeeValueText = maxFiatFee.format { fiat(appCurrency.code, appCurrency.symbol) } + val maxFeeCryptoValueText = maxNetworkFee.format { crypto(cryptoCurrency) } + val maxFiatFeeValueText = maxNetworkFeeFiat.format { fiat(appCurrency.code, appCurrency.symbol) } val minAmountCryptoText = minAmount.format { crypto(cryptoCurrency) } val minAmountFiat = tokenFiatRate?.let(minAmount::multiply) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt index 8610f6a652..658dd165bb 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt @@ -86,7 +86,7 @@ internal class YieldSupplyStopEarningModel @Inject constructor( val uiState: StateFlow field: MutableStateFlow = MutableStateFlow( YieldSupplyActionUM( - title = resourceReference(R.string.yield_module_stop_earning), + title = resourceReference(R.string.yield_module_stop_earning_sheet_title), subtitle = resourceReference( id = R.string.yield_module_stop_earning_sheet_description, formatArgs = wrappedList(cryptoCurrency.symbol), From 4242a8f2fb420895a5985d095bea685fad696aa8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 4 Nov 2025 18:03:47 +0300 Subject: [PATCH 15/19] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 32 ---- .../java/com/tangem/tap/di/ActivityModule.kt | 19 -- .../tap/di/domain/TokensDomainModule.kt | 9 - .../tangem/data/tokens/di/TokensDataModule.kt | 16 -- ...ultPolkadotAccountHealthCheckRepository.kt | 179 ------------------ .../GetPolkadotCheckHasImmortalUseCase.kt | 11 -- .../tokens/GetPolkadotCheckHasResetUseCase.kt | 12 -- .../RunPolkadotAccountHealthCheckUseCase.kt | 15 -- .../PolkadotAccountHealthCheckRepository.kt | 14 -- .../implementors/MultiWalletContentLoader.kt | 11 +- .../MultiWalletContentLoaderFactory.kt | 3 - .../SingleWalletWithTokenContentLoader.kt | 3 - ...ngleWalletWithTokenContentLoaderFactory.kt | 3 - .../subscribers/BasicTokenListSubscriber.kt | 29 +-- .../MultiWalletTokenListSubscriber.kt | 2 - .../SingleWalletWithTokenListSubscriber.kt | 2 - 16 files changed, 6 insertions(+), 354 deletions(-) delete mode 100644 data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultPolkadotAccountHealthCheckRepository.kt delete mode 100644 domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetPolkadotCheckHasImmortalUseCase.kt delete mode 100644 domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetPolkadotCheckHasResetUseCase.kt delete mode 100644 domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RunPolkadotAccountHealthCheckUseCase.kt delete mode 100644 domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PolkadotAccountHealthCheckRepository.kt diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 9d6af9296f..0ef437226d 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.core.net.toUri import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen -import androidx.lifecycle.Lifecycle import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import arrow.core.getOrElse @@ -44,11 +43,8 @@ import com.tangem.domain.settings.SetGoogleServicesAvailabilityUseCase import com.tangem.domain.settings.ShouldInitiallyAskPermissionUseCase import com.tangem.domain.settings.repositories.SettingsRepository import com.tangem.domain.staking.SendUnsubmittedHashesUseCase -import com.tangem.domain.tokens.GetPolkadotCheckHasImmortalUseCase -import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.domain.wallets.usecase.ClearAllHotWalletContextualUnlockUseCase -import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent import com.tangem.features.hotwallet.HotWalletFeatureToggles import com.tangem.features.tangempay.TangemPayFeatureToggles import com.tangem.features.tester.api.TesterMenuLauncher @@ -115,12 +111,6 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder { @Inject lateinit var sendUnsubmittedHashesUseCase: SendUnsubmittedHashesUseCase - @Inject - lateinit var getPolkadotCheckHasResetUseCase: GetPolkadotCheckHasResetUseCase - - @Inject - lateinit var getPolkadotCheckHasImmortalUseCase: GetPolkadotCheckHasImmortalUseCase - @Inject lateinit var analyticsEventsHandler: AnalyticsEventHandler @@ -228,7 +218,6 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder { initContent() - observePolkadotAccountHealthCheck() sendStakingUnsubmittedHashes() checkGoogleServicesAvailability() @@ -436,27 +425,6 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder { } } - private fun observePolkadotAccountHealthCheck() { - lifecycleScope.launch { - getPolkadotCheckHasResetUseCase() - .flowWithLifecycle(lifecycle, minActiveState = Lifecycle.State.CREATED) - .distinctUntilChanged() - .collect { - analyticsEventsHandler.send(WalletScreenAnalyticsEvent.Token.PolkadotAccountReset(it.second)) - } - } - lifecycleScope.launch { - getPolkadotCheckHasImmortalUseCase() - .flowWithLifecycle(lifecycle, minActiveState = Lifecycle.State.CREATED) - .distinctUntilChanged() - .collect { (_, hasImmortalTransaction) -> - analyticsEventsHandler.send( - WalletScreenAnalyticsEvent.Token.PolkadotImmortalTransactions(hasImmortalTransaction), - ) - } - } - } - private fun sendStakingUnsubmittedHashes() { lifecycleScope.launch { sendUnsubmittedHashesUseCase.invoke() diff --git a/app/src/main/java/com/tangem/tap/di/ActivityModule.kt b/app/src/main/java/com/tangem/tap/di/ActivityModule.kt index e963c1f140..1ee8ec2a46 100644 --- a/app/src/main/java/com/tangem/tap/di/ActivityModule.kt +++ b/app/src/main/java/com/tangem/tap/di/ActivityModule.kt @@ -5,10 +5,7 @@ import com.tangem.datasource.exchangeservice.swap.ExpressServiceLoader import com.tangem.domain.card.ScanCardUseCase import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.exchange.RampStateManager -import com.tangem.domain.tokens.GetPolkadotCheckHasImmortalUseCase -import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository import com.tangem.sdk.api.TangemSdkManager import com.tangem.tap.domain.scanCard.repository.DefaultScanCardRepository import com.tangem.tap.network.exchangeServices.DefaultRampManager @@ -66,20 +63,4 @@ internal object ActivityModule { fun provideActivityDelayedWorkCoroutineScope(): CoroutineScope { return CoroutineScope(SupervisorJob() + Dispatchers.IO) } - - @Provides - @Singleton - fun provideGetPolkadotCheckHasResetUseCase( - polkadotAccountHealthCheckRepository: PolkadotAccountHealthCheckRepository, - ): GetPolkadotCheckHasResetUseCase { - return GetPolkadotCheckHasResetUseCase(polkadotAccountHealthCheckRepository) - } - - @Provides - @Singleton - fun provideGetPolkadotCheckHasImmortalUseCase( - polkadotAccountHealthCheckRepository: PolkadotAccountHealthCheckRepository, - ): GetPolkadotCheckHasImmortalUseCase { - return GetPolkadotCheckHasImmortalUseCase(polkadotAccountHealthCheckRepository) - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index 960857e2eb..9a22983e55 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -22,7 +22,6 @@ import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations import com.tangem.domain.tokens.operations.CachedCurrenciesStatusesOperations import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.CurrencyChecksRepository -import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository import com.tangem.domain.tokens.repository.TokenReceiveWarningsViewedRepository import com.tangem.domain.tokens.repository.YieldSupplyWarningsViewedRepository import com.tangem.domain.tokens.wallet.WalletBalanceFetcher @@ -334,14 +333,6 @@ internal object TokensDomainModule { return IsAmountSubtractAvailableUseCase(currenciesRepository, dispatchers) } - @Provides - @Singleton - fun provideRunPolkadotAccountHealthCheckUseCase( - repository: PolkadotAccountHealthCheckRepository, - ): RunPolkadotAccountHealthCheckUseCase { - return RunPolkadotAccountHealthCheckUseCase(repository) - } - @Provides @Singleton fun provideGetNetworkStatusesUseCase(networksRepository: NetworksRepository): GetNetworkAddressesUseCase { diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt index 23f10b2f4d..8495e3e6fa 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt @@ -7,7 +7,6 @@ import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory import com.tangem.data.common.currency.UserTokensSaver import com.tangem.data.tokens.repository.DefaultCurrenciesRepository import com.tangem.data.tokens.repository.DefaultCurrencyChecksRepository -import com.tangem.data.tokens.repository.DefaultPolkadotAccountHealthCheckRepository import com.tangem.data.tokens.repository.DefaultTokenReceiveWarningsViewedRepository import com.tangem.data.tokens.repository.DefaultYieldSupplyWarningsViewedRepository import com.tangem.datasource.api.tangemTech.TangemTechApi @@ -18,7 +17,6 @@ import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.CurrencyChecksRepository -import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository import com.tangem.domain.tokens.repository.TokenReceiveWarningsViewedRepository import com.tangem.domain.tokens.repository.YieldSupplyWarningsViewedRepository import com.tangem.domain.walletmanager.WalletManagersFacade @@ -75,20 +73,6 @@ internal object TokensDataModule { ) } - @Provides - @Singleton - fun providePolkadotAccountHealthCheckRepository( - walletManagersFacade: WalletManagersFacade, - appPreferencesStore: AppPreferencesStore, - dispatchers: CoroutineDispatcherProvider, - ): PolkadotAccountHealthCheckRepository { - return DefaultPolkadotAccountHealthCheckRepository( - walletManagersFacade = walletManagersFacade, - appPreferencesStore = appPreferencesStore, - dispatchers = dispatchers, - ) - } - @Provides @Singleton fun provideTokenReceiveWarningsViewedRepository( diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultPolkadotAccountHealthCheckRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultPolkadotAccountHealthCheckRepository.kt deleted file mode 100644 index 2e2a8ae876..0000000000 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultPolkadotAccountHealthCheckRepository.kt +++ /dev/null @@ -1,179 +0,0 @@ -package com.tangem.data.tokens.repository - -import androidx.datastore.preferences.core.Preferences -import com.tangem.blockchain.blockchains.polkadot.AccountCheckProvider -import com.tangem.blockchain.blockchains.polkadot.network.accounthealthcheck.ExtrinsicListItemResponse -import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.BlockchainSdkError -import com.tangem.blockchainsdk.utils.toBlockchain -import com.tangem.datasource.local.preferences.AppPreferencesStore -import com.tangem.datasource.local.preferences.PreferencesKeys.POLKADOT_HEALTH_CHECKED_IMMUTABLE_ACCOUNTS_KEY -import com.tangem.datasource.local.preferences.PreferencesKeys.POLKADOT_HEALTH_CHECKED_RESET_ACCOUNTS_KEY -import com.tangem.datasource.local.preferences.PreferencesKeys.POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX_KEY -import com.tangem.datasource.local.preferences.utils.getObjectMapSync -import com.tangem.datasource.local.preferences.utils.getObjectSetSync -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository -import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.asSharedFlow -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import kotlinx.coroutines.withContext -import timber.log.Timber -import java.util.concurrent.ConcurrentHashMap - -internal class DefaultPolkadotAccountHealthCheckRepository( - private val walletManagersFacade: WalletManagersFacade, - private val appPreferencesStore: AppPreferencesStore, - private val dispatchers: CoroutineDispatcherProvider, -) : PolkadotAccountHealthCheckRepository { - - private val hasImmortalTransaction = MutableSharedFlow>() - private val hasResetTransaction = MutableSharedFlow>() - - private val mutex = Mutex() - private val mutexes = ConcurrentHashMap() - - override suspend fun runCheck(userWalletId: UserWalletId, network: Network) { - // Run Polkadot account health check - if (network.toBlockchain() != Blockchain.Polkadot) return - - val walletManager = walletManagersFacade.getOrCreateWalletManager(userWalletId, network) - val address = requireNotNull(walletManager?.wallet?.address) { - Timber.e("Address is null") - return - } - val accountCheckProvider = requireNotNull(walletManager as? AccountCheckProvider) { - Timber.e("Unable to cast wallet manager to AccountCheckProvider") - return - } - - // use a separate mutexForKey for each key to avoid multiple calls block() to the same key - // also used mutex to safe create mutexForKey, otherwise it can lead to multiple calls for the same key - val mutexForKey = mutex.withLock { mutexes.getOrPut(address) { Mutex() } } - mutexForKey.withLock { - withContext(dispatchers.io) { - checkHasReset(accountCheckProvider, address) - checkHasImmortal(accountCheckProvider, address) - } - } - } - - override fun subscribeToHasImmortalResults() = hasImmortalTransaction.asSharedFlow() - - override fun subscribeToHasResetResults() = hasResetTransaction.asSharedFlow() - - private suspend fun checkHasReset(polkadotManager: AccountCheckProvider, address: String) { - val checkedAddresses = appPreferencesStore.getObjectSetSync(POLKADOT_HEALTH_CHECKED_RESET_ACCOUNTS_KEY) - if (checkedAddresses.contains(address)) return - runCatching { - val accountInfo = requireNotNull(polkadotManager.getAccountInfo().account) { - Timber.e("Account info is null") - } - val nonce = accountInfo.nonce - val extrinsicCount = accountInfo.countExtrinsic - - // Account was reset - if (nonce != null && extrinsicCount != null) { - val hasReset = nonce < extrinsicCount - updateChecked(address, POLKADOT_HEALTH_CHECKED_RESET_ACCOUNTS_KEY) - hasResetTransaction.emit(address to hasReset) - } - }.onFailure { - if ((it as? BlockchainSdkError.CustomError)?.customMessage == ACCOUNT_NOT_FOUND) { - updateChecked(address, POLKADOT_HEALTH_CHECKED_RESET_ACCOUNTS_KEY) - } - } - } - - private suspend fun checkHasImmortal(accountCheckerProvider: AccountCheckProvider, address: String) { - val checkedAddresses = - appPreferencesStore.getObjectSetSync(POLKADOT_HEALTH_CHECKED_IMMUTABLE_ACCOUNTS_KEY) - if (checkedAddresses.contains(address)) return - - runCatching { - do { - // Getting batch of extrinsics to check - val lastChecked = appPreferencesStore.getObjectMapSync(POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX_KEY) - val lastExtrinsic = lastChecked[address] - val extrinsicListResult = accountCheckerProvider.getExtrinsicList(afterExtrinsicId = lastExtrinsic) - extrinsicListResult.extrinsic - ?.forEach { tx -> - // Checking extrinsic one by one - if (checkTx(tx, address, accountCheckerProvider)) return - } - } while (!extrinsicListResult.extrinsic.isNullOrEmpty()) - - // We checked all transactions up to current moment and did not found an `immortal` transaction - hasImmortalTransaction.emit(address to false) - updateChecked(address, POLKADOT_HEALTH_CHECKED_IMMUTABLE_ACCOUNTS_KEY) - clearLastCheckedTransaction(address) - } - } - - private suspend fun checkTx( - tx: ExtrinsicListItemResponse, - address: String, - accountCheckerProvider: AccountCheckProvider, - ): Boolean { - val hash = tx.hash - val id = tx.id - if (hash != null && id != null) { - val details = accountCheckerProvider.getExtrinsicDetail(hash) - - // We found an `immortal` transaction - if (details.lifetime == null) { - hasImmortalTransaction.emit(address to true) - updateChecked(address, POLKADOT_HEALTH_CHECKED_IMMUTABLE_ACCOUNTS_KEY) - clearLastCheckedTransaction(address) - return true - } - - // Saving last checked transaction - updateLastCheckedTransaction(address, id) - } - return false - } - - private suspend fun updateLastCheckedTransaction(address: String, txId: Long) { - appPreferencesStore.editData { - val savedList = it.getObjectMap(POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX_KEY) - val updatedList = savedList.toMutableMap() - updatedList[address] = txId - it.setObjectMap(POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX_KEY, updatedList) - } - } - - private suspend fun clearLastCheckedTransaction(address: String) { - appPreferencesStore.editData { mutablePreferences -> - val savedList = mutablePreferences.getObjectMap(POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX_KEY) - val updatedList = savedList.toMutableMap() - updatedList.remove(address) - mutablePreferences.setObjectMap(POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX_KEY, updatedList) - } - } - - private suspend fun updateChecked(address: String, key: Preferences.Key) { - appPreferencesStore.editData { mutablePreferences -> - val savedList = mutablePreferences.getObjectSet(key) - val updatedList = savedList?.toMutableSet() ?: mutableSetOf() - updatedList.add(address) - - if (updatedList.isNotEmpty()) { - mutablePreferences.setObjectSet( - key, - updatedList.toSet(), - ) - } else { - mutablePreferences.remove(key) - } - } - } - - private companion object { - const val ACCOUNT_NOT_FOUND = "Record Not Found" - } -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetPolkadotCheckHasImmortalUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetPolkadotCheckHasImmortalUseCase.kt deleted file mode 100644 index 527f6e1703..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetPolkadotCheckHasImmortalUseCase.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.tangem.domain.tokens - -import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository -import kotlinx.coroutines.flow.Flow - -class GetPolkadotCheckHasImmortalUseCase( - private val polkadotAccountHealthCheckRepository: PolkadotAccountHealthCheckRepository, -) { - operator fun invoke(): Flow> = - polkadotAccountHealthCheckRepository.subscribeToHasImmortalResults() -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetPolkadotCheckHasResetUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetPolkadotCheckHasResetUseCase.kt deleted file mode 100644 index 33ce7e960e..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetPolkadotCheckHasResetUseCase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tangem.domain.tokens - -import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository -import kotlinx.coroutines.flow.Flow - -class GetPolkadotCheckHasResetUseCase( - private val polkadotAccountHealthCheckRepository: PolkadotAccountHealthCheckRepository, -) { - - operator fun invoke(): Flow> = - polkadotAccountHealthCheckRepository.subscribeToHasResetResults() -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RunPolkadotAccountHealthCheckUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RunPolkadotAccountHealthCheckUseCase.kt deleted file mode 100644 index 9f665e442e..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RunPolkadotAccountHealthCheckUseCase.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import com.tangem.domain.models.network.Network -import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository -import com.tangem.domain.models.wallet.UserWalletId - -class RunPolkadotAccountHealthCheckUseCase( - private val polkadotAccountHealthCheckRepository: PolkadotAccountHealthCheckRepository, -) { - - suspend operator fun invoke(userWalletId: UserWalletId, network: Network): Either = Either.catch { - polkadotAccountHealthCheckRepository.runCheck(userWalletId, network) - } -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PolkadotAccountHealthCheckRepository.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PolkadotAccountHealthCheckRepository.kt deleted file mode 100644 index 88ca5927ae..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PolkadotAccountHealthCheckRepository.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.tangem.domain.tokens.repository - -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWalletId -import kotlinx.coroutines.flow.Flow - -interface PolkadotAccountHealthCheckRepository { - - suspend fun runCheck(userWalletId: UserWalletId, network: Network) - - fun subscribeToHasImmortalResults(): Flow> - - fun subscribeToHasResetResults(): Flow> -} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt index 5eb6975247..b08d9fb996 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt @@ -2,17 +2,17 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors import com.tangem.core.decompose.di.ModelScoped import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase +import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.nft.GetNFTCollectionsUseCase import com.tangem.domain.promo.GetStoryContentUseCase -import com.tangem.domain.tokens.ApplyTokenListSortingUseCase -import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase -import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.staking.usecase.StakingApyFlowUseCase +import com.tangem.domain.tokens.ApplyTokenListSortingUseCase +import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.wallets.repository.WalletsRepository import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents +import com.tangem.feature.wallet.presentation.account.AccountDependencies import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender @@ -21,7 +21,6 @@ import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenList import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController import com.tangem.feature.wallet.presentation.wallet.subscribers.* -import com.tangem.feature.wallet.presentation.account.AccountDependencies @Suppress("LongParameterList") @ModelScoped @@ -38,7 +37,6 @@ internal class MultiWalletContentLoader( private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase, private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory, - private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, private val walletsRepository: WalletsRepository, @@ -59,7 +57,6 @@ internal class MultiWalletContentLoader( tokenListStore = tokenListStore, getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, applyTokenListSortingUseCase = applyTokenListSortingUseCase, - runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, accountDependencies = accountDependencies, yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase, stakingApyFlowUseCase = stakingApyFlowUseCase, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt index 63d8447f57..e2dae7da64 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt @@ -5,7 +5,6 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.nft.GetNFTCollectionsUseCase import com.tangem.domain.promo.GetStoryContentUseCase import com.tangem.domain.tokens.ApplyTokenListSortingUseCase -import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.staking.usecase.StakingApyFlowUseCase @@ -35,7 +34,6 @@ internal class MultiWalletContentLoaderFactory @Inject constructor( private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase, private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, - private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, private val walletsRepository: WalletsRepository, @@ -59,7 +57,6 @@ internal class MultiWalletContentLoaderFactory @Inject constructor( walletWarningsAnalyticsSender = walletWarningsAnalyticsSender, walletWarningsSingleEventSender = walletWarningsSingleEventSender, applyTokenListSortingUseCase = applyTokenListSortingUseCase, - runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, getStoryContentUseCase = getStoryContentUseCase, shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase, walletsRepository = walletsRepository, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt index 7b01ba0107..154c71724b 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt @@ -2,7 +2,6 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.promo.GetStoryContentUseCase -import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.staking.usecase.StakingApyFlowUseCase import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase @@ -30,7 +29,6 @@ internal class SingleWalletWithTokenContentLoader( private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory, private val tokenListStore: MultiWalletTokenListStore, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, - private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, private val accountDependencies: AccountDependencies, @@ -48,7 +46,6 @@ internal class SingleWalletWithTokenContentLoader( walletWithFundsChecker = walletWithFundsChecker, tokenListStore = tokenListStore, getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, - runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, accountDependencies = accountDependencies, yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase, stakingApyFlowUseCase = stakingApyFlowUseCase, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt index 4c178e1136..de00f8f290 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt @@ -3,7 +3,6 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors import com.tangem.core.decompose.di.ModelScoped import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.promo.GetStoryContentUseCase -import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.staking.usecase.StakingApyFlowUseCase import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase @@ -31,7 +30,6 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor( private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, - private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, private val accountDependencies: AccountDependencies, @@ -51,7 +49,6 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor( getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, walletWarningsAnalyticsSender = walletWarningsAnalyticsSender, walletWarningsSingleEventSender = walletWarningsSingleEventSender, - runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, getStoryContentUseCase = getStoryContentUseCase, shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase, accountDependencies = accountDependencies, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt index 8fbd5a1d74..f5b62855de 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt @@ -14,10 +14,9 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.tokenlist.TokenList import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.staking.model.stakekit.Yield -import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase +import com.tangem.domain.staking.usecase.StakingApyFlowUseCase import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase -import com.tangem.domain.staking.usecase.StakingApyFlowUseCase import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents import com.tangem.feature.wallet.presentation.account.AccountDependencies import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender @@ -43,7 +42,6 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { protected abstract val tokenListAnalyticsSender: TokenListAnalyticsSender protected abstract val walletWithFundsChecker: WalletWithFundsChecker protected abstract val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase - protected abstract val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase protected abstract val accountDependencies: AccountDependencies protected abstract val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase protected abstract val stakingApyFlowUseCase: StakingApyFlowUseCase @@ -80,8 +78,6 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { coroutineScope.launch { onTokenListReceived(maybeTokenList) }.saveIn(onTokenListReceivedJobHolder) - - coroutineScope.launch { startCheck(maybeTokenList) } }, flow2 = appCurrencyFlow(), flow3 = yieldSupplyApyFlow(), @@ -137,20 +133,6 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { walletWithFundsChecker.check(tokenList) } - private suspend fun startCheck(maybeTokenList: Lce) { - // Run Polkadot account health check - maybeTokenList.getOrNull()?.let { tokenList -> - tokenList - .flattenCurrencies() - .forEach { - runPolkadotAccountHealthCheckUseCase( - userWalletId = userWallet.walletId, - network = it.currency.network, - ) - } - } - } - private fun createAccountListFlow(coroutineScope: CoroutineScope): Flow<*> = combine6( flow1 = accountListFlow(coroutineScope) .onEach { accountStatusList -> @@ -161,14 +143,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { ) }.saveIn(sendAnalyticsJobHolder) } - .distinctUntilChanged() - .onEach { accountList -> - // todo account see[onAccountListReceived] - // coroutineScope.launch { onAccountListReceived() }.saveIn(onTokenListReceivedJobHolder) - - accountList.flattenTokens() - .forEach { tokenList -> startCheck(Lce.Content(tokenList)) } - }, + .distinctUntilChanged(), flow2 = appCurrencyFlow(), flow3 = accountDependencies.expandedAccountsHolder.expandedAccounts(userWallet), flow4 = accountDependencies.isAccountsModeEnabledUseCase(), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt index f64dafc766..8cea37e832 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt @@ -12,7 +12,6 @@ import com.tangem.domain.models.tokenlist.TokenList import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.staking.usecase.StakingApyFlowUseCase import com.tangem.domain.tokens.ApplyTokenListSortingUseCase -import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents @@ -34,7 +33,6 @@ internal class MultiWalletTokenListSubscriber( override val tokenListAnalyticsSender: TokenListAnalyticsSender, override val walletWithFundsChecker: WalletWithFundsChecker, override val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, - override val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, override val accountDependencies: AccountDependencies, override val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, override val stakingApyFlowUseCase: StakingApyFlowUseCase, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt index 15892dd13b..27f863f68a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt @@ -8,7 +8,6 @@ import com.tangem.domain.core.lce.LceFlow import com.tangem.domain.models.tokenlist.TokenList import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.staking.usecase.StakingApyFlowUseCase -import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents @@ -29,7 +28,6 @@ internal class SingleWalletWithTokenListSubscriber( override val tokenListAnalyticsSender: TokenListAnalyticsSender, override val walletWithFundsChecker: WalletWithFundsChecker, override val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, - override val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, override val accountDependencies: AccountDependencies, override val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase, override val stakingApyFlowUseCase: StakingApyFlowUseCase, From 1aa98da0e04d3e3e9a3f736e1241f7eb6883abe0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 4 Nov 2025 23:47:52 +0300 Subject: [PATCH 16/19] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 96290bd78f..852b769c33 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-1298" +tangemBlockchainSdk = "releases-5.30-1299" #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 e15abd0a9a499aaf9167807f370ae430592107f0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 4 Nov 2025 20:48:12 +0000 Subject: [PATCH 17/19] 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 852b769c33..b7a7456028 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-1299" +tangemBlockchainSdk = "develop-1294" #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 ^ From 5e7550ab07b35eb5af4fdea5687fa86abb1002bb Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 5 Nov 2025 13:51:23 +0300 Subject: [PATCH 18/19] Updated on 2026-08-14 --- .../local/preferences/PreferencesKeys.kt | 10 ---------- .../analytics/WalletScreenAnalyticsEvent.kt | 20 ------------------- 2 files changed, 30 deletions(-) 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 a91cb3cf09..b41be76cea 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 @@ -62,16 +62,6 @@ object PreferencesKeys { val APP_LOGS_KEY by lazy { stringPreferencesKey(name = "app_logs") } - val POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX_KEY by lazy { - stringPreferencesKey(name = "POLKADOT_HEALTH_CHECK_LAST_INDEXED_TX") - } - val POLKADOT_HEALTH_CHECKED_RESET_ACCOUNTS_KEY by lazy { - stringPreferencesKey(name = "POLKADOT_HEALTH_CHECKED_RESET_ACCOUNTS") - } - val POLKADOT_HEALTH_CHECKED_IMMUTABLE_ACCOUNTS_KEY by lazy { - stringPreferencesKey(name = "POLKADOT_HEALTH_CHECKED_IMMUTABLE_ACCOUNTS") - } - val SEND_TAP_HELP_PREVIEW_KEY by lazy { booleanPreferencesKey(name = "sendTapHelpPreview") } val WAS_APPLICATION_STOPPED_KEY by lazy { booleanPreferencesKey(name = "applicationStopped") } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt index 135b2c2f6c..54d3a4cca2 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt @@ -46,26 +46,6 @@ sealed class WalletScreenAnalyticsEvent { ) } - sealed class Token( - event: String, - params: Map = mapOf(), - ) : AnalyticsEvent(category = "Token", event = event, params = params) { - - class PolkadotAccountReset(hasReset: Boolean) : Token( - event = "Polkadot Account Reset", - params = mapOf( - AnalyticsParam.STATE to if (hasReset) "Yes" else "No", - ), - ) - - class PolkadotImmortalTransactions(hasImmortalTransaction: Boolean) : Token( - event = "Polkadot Immortal Transactions", - params = mapOf( - AnalyticsParam.STATE to if (hasImmortalTransaction) "Yes" else "No", - ), - ) - } - sealed class MainScreen( event: String, params: Map = mapOf(), From 0f1394a3d11eb6fc900d2353fdde2f1581ae4a10 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 5 Nov 2025 10:51:45 +0000 Subject: [PATCH 19/19] 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 852b769c33..b7a7456028 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-1299" +tangemBlockchainSdk = "develop-1294" #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 ^