From b47d65db1b628d3ff58a1a89ac2933900edf1fc6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 21 Oct 2025 14:38:48 +0500 Subject: [PATCH 01/13] Updated on 2026-08-14 --- .../send/v2/subcomponents/amount/model/SendAmountModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt index cd838ffa32..f3271ad09f 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt @@ -142,8 +142,8 @@ internal class SendAmountModel @Inject constructor( ) { newCryptoCurrencyStatus, account, isAccountsMode -> maxAmountBoundary = MaxEnterAmountConverter().convert(newCryptoCurrencyStatus) cryptoCurrencyStatus = newCryptoCurrencyStatus - initMinBoundary(cryptoCurrencyStatus, account, isAccountsMode) - }.flowOn(dispatchers.default) + initMinBoundary(newCryptoCurrencyStatus, account, isAccountsMode) + }.flowOn(dispatchers.main) .launchIn(modelScope) } From 748793e67d7d51d45ee246466b3f45a76d9c8bb8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 21 Oct 2025 15:15:32 +0500 Subject: [PATCH 02/13] Updated on 2026-08-14 --- .../tangem/common/ui/amountScreen/ui/AmountFieldContainer.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/ui/src/main/java/com/tangem/common/ui/amountScreen/ui/AmountFieldContainer.kt b/common/ui/src/main/java/com/tangem/common/ui/amountScreen/ui/AmountFieldContainer.kt index db265212a0..12335b79ad 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/amountScreen/ui/AmountFieldContainer.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/amountScreen/ui/AmountFieldContainer.kt @@ -1,6 +1,9 @@ package com.tangem.common.ui.amountScreen.ui import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.togetherWith import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -127,6 +130,8 @@ private fun AmountInfoMain(amountUM: AmountState, modifier: Modifier = Modifier) AnimatedContent( targetState = amountUM, modifier = modifier, + contentKey = { amountUM.javaClass }, // Show animation only when the state type changes [Empty -> Data] + transitionSpec = { fadeIn().togetherWith(fadeOut()) }, ) { currentAmount -> Column( verticalArrangement = Arrangement.spacedBy(2.dp), From 8c258d0b7c492144bb582f82455bc27486a4af12 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 22 Oct 2025 12:51:42 +0500 Subject: [PATCH 03/13] Updated on 2026-08-14 --- .../common/ui/notifications/NotificationUM.kt | 8 +++ .../ui/tokens/TokenItemStateConverter.kt | 4 +- core/res/src/main/res/values-de/strings.xml | 1 + core/res/src/main/res/values-ja/strings.xml | 17 +++-- core/res/src/main/res/values-ru/strings.xml | 5 +- .../src/main/res/values-uk-rUA/strings.xml | 1 + core/res/src/main/res/values/strings.xml | 57 ++++++++------- .../DefaultCurrencyChecksRepository.kt | 25 ------- .../model/warnings/CryptoCurrencyWarning.kt | 6 -- .../tokens/GetCurrencyWarningsUseCase.kt | 26 +------ .../repository/CurrencyChecksRepository.kt | 7 -- .../usecase/YieldSupplyGetMaxFeeUseCase.kt | 5 +- .../entity/TokenReceiveStateFactory.kt | 6 -- .../TokenDetailsNotificationConverter.kt | 4 -- .../supply/impl/main/entity/YieldSupplyUM.kt | 2 +- .../impl/main/model/YieldSupplyModel.kt | 30 ++++---- .../impl/main/ui/YieldSupplyBlockContent.kt | 6 +- .../active/YieldSupplyActiveComponent.kt | 2 + .../entity/YieldSupplyActiveContentUM.kt | 3 +- .../model/YieldSupplyActiveEntryModel.kt | 7 ++ .../active/model/YieldSupplyActiveModel.kt | 70 ++++++++++++++----- .../active/ui/YieldSupplyActiveContent.kt | 63 ++++++++++++----- 22 files changed, 192 insertions(+), 163 deletions(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt index 8c2f75bb85..66b28de458 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt @@ -274,6 +274,14 @@ sealed class NotificationUM(val config: NotificationConfig) { title = resourceReference(id = R.string.yield_module_balance_info_sheet_title, wrappedList(tokenName)), subtitle = resourceReference(id = R.string.yield_module_balance_info_sheet_subtitle), ) + + data class YieldSupplyNotAllAmountSupplied(val formattedAmount: String, val symbol: String) : Warning( + title = resourceReference( + id = R.string.yield_module_amount_not_transfered_to_aave_title, + formatArgs = wrappedList(formattedAmount, symbol), + ), + subtitle = TextReference.EMPTY, + ) } open class Info( 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 0c5042c6d8..17aa2184d7 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 @@ -20,7 +20,6 @@ import com.tangem.domain.models.StatusSource 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.currency.yieldSupplyNotAllAmountSupplied import com.tangem.domain.models.staking.YieldBalance import com.tangem.domain.staking.utils.getTotalWithRewardsStakingBalance import com.tangem.utils.StringsSigns.DASH_SIGN @@ -271,8 +270,7 @@ class TokenItemStateConverter( isFlickering = status.value.isFlickering(), icons = buildList { if (status.value.yieldSupplyStatus?.isActive == true && - status.value.yieldSupplyStatus?.isAllowedToSpend == false || - status.yieldSupplyNotAllAmountSupplied() + status.value.yieldSupplyStatus?.isAllowedToSpend == false ) { TokenItemState.FiatAmountState.Content.IconUM( iconRes = R.drawable.ic_alert_triangle_20, diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index c5d3a6d70e..ee000bb82f 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -1679,6 +1679,7 @@ Der erhaltene Betrag %1$s %2$s wurde nicht auf Aave eingezahlt. Aktuelle Gebühr Maximale Gebühr + Dies ist die niedrigste Einzahlung, die an Aave gesendet werden kann. Um Einzahlungen rentabel zu halten, verarbeiten wir sie nicht, wenn die Netzwerkgebühren 4 % des Betrags übersteigen. Gebührenpolitik Die Netzwerkgebühr ist derzeit zu hoch. Warte, bis sie unter Dein Limit fällt. Historische Renditen diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 16107ea2c1..c1f18f6577 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 @@ このアカウントをアーカイブしますが、いつでも復元できます。 アカウント アカウントが保存されました + 報酬用のアカウント アカウント番号%s — アドレス導出に使用されます。 アカウントを追加 保存 @@ -969,6 +970,10 @@ このカードを使用して、現在のウォレットの他のカードのアクセスコードを回復させられないことを認識しています。 工場出荷時設定にリセットすると、選択したカードやリングからウォレットが完全に削除されます。現在のウォレットを復元したり、カードやリングを使用してアクセスコードを復元することはできません。 工場出荷時の状態にリセットすると、選択したカードやリングからウォレットが完全に削除され、アプリから削除されます。現在のウォレットを復元することはできません。 + すべてのTangemデバイスがリセットされました。 + アクティベーション処理中に問題が発生しました。カードを1枚ずつリセットしてください。 + カード認証に失敗しました + 続行するには次のデバイスをリセットしてください Tangem Ringユーザーは、11/15日までChangelly経由でスワップを3回手数料ゼロで行えます! 今すぐ手数料0% でスワップしましょう! アプリにログインして、カードまたはリングをスキャンせずに残高を確認できます @@ -1728,8 +1733,8 @@ いいえ、すべて送信します %s XTZを減らす 次回ウォレットにチャージするときに手数料の増加を避けるには、金額を%s XTZ減らしてください。 - 資産残高に関するテキスト [プレースホルダー] %sはAaveに預けられています + 受け取った金額%1$s %2$sはAaveに入金されませんでした。 承認する 前回の承認に問題があったため、新しい承認が必要です。手続き方法を選択してください。 承認が必要 @@ -1743,6 +1748,8 @@ 年利%1$s%% 利用可能 現在のAPY + 貸付のためにチャージする際は、ネットワーク手数料が金額から差し引かれます(手数料は常に%1$s以下です)。 + 現在、ネットワーク手数料が高すぎるため貸付を実行できません。手数料が%1$s以下に下がり次第、資金が供給されます。 私の資金 あなたの%1$sはAaveに預けられ、利息が付きます。あなたは%2$sトークンを保有しており、これは残高を表し、時間の経過とともに増加します。入金すると、資金はAaveに預け入れられ、取引手数料を差し引いた利息が付きます。 利回りを得る @@ -1758,7 +1765,7 @@ 最低入金額 手数料ポリシー Tangemはまた、得られた利回りに対して3%のサービス手数料を差し引きます。 - ネットワーク手数料が現在高すぎます。設定した上限を下回るまで待機しています。 + ネットワーク手数料が下がるか、残高が必要な最低額に達すると、自動的にAaveへ送金されます。 過去のリターン ここに説明を入力してください。1〜3行が理想的です。[プレースホルダー] トークン承認が必要 @@ -1787,14 +1794,14 @@ 次回以降の入金は自動的にAaveに供給されます。 アクティブ 停止中 - 収益を停止する + 利回りモードを無効にする オフにすると、Aaveから資金が引き出され、ウォレットの%sに戻され、報酬の獲得が停止されます。 出金金額からネットワーク手数料が差し引かれます。 供給APY APY - あなたの資産を眠らせない — 残高を運用して利息を得ましょう。 + 自分で管理しながら、資金をバックグラウンドで運用しましょう。 利息は自動的に発生します - Aaveの利回り + 利回りモード 入金の処理中 残高を活用 自動 diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 168ba8b435..9b73434b2d 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -1569,6 +1569,7 @@ Нет, отправить все Уменьшить на %s XTZ Чтобы не платить повышенную комиссию при следующем пополнении кошелька, уменьшите сумму на %s XTZ + Ваши средства сейчас размещены в протоколе AAVE, но вы можете управлять ими в любое время. Ваш %s внесён в Aave Выдать разрешение Что-то пошло не так с вашим предыдущим разрешением, поэтому требуется новое. Выберите, как хотите продолжить. @@ -1592,7 +1593,7 @@ Все следующие пополнения %s автоматически поступят в Aave с удержанием комиссии за транзакцию. Если комиссия сети превысит максимальный лимит, транзакция не будет выполнена до тех пор, пока комиссия не снизится. Вы сможете изменить этот лимит позже. Максимальная комиссия - Комиссия за транзакцию должна быть ниже 4% от суммы депозита. Tangem переведёт средства в Aave, как только это условие будет выполнено. + Это минимальный депозит, который можно отправить в Aave. Чтобы депозиты оставались прибыльными, мы не обрабатываем их, когда комиссия сети превышает 4% от суммы. Минимальный депозит Политика комиссий Tangem взимает комиссию за обслуживание в размере 3% от полученного дохода. @@ -1602,7 +1603,7 @@ Проверьте ваше интернет соединение Информация о комиссии недоступна Каждое пополнение вашего адреса автоматически будет отправляться в Aave. - Ваш баланс работает автоматически + Автоперевод в AAVE Отправляйте, обменивайте или продавайте свои средства мгновенно, когда захотите. Мгновенный вывод средств Как это работает? 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..b13f5ecb1d 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -1430,4 +1430,5 @@ Ні, відправити все Зменшити на %s XTZ Щоб не платити підвищену комісію при наступному поповненні гаманця, зменште суму на %s XTZ + Це найменший депозит, який можна надіслати в Aave. Щоб депозити залишалися прибутковими, ми не обробляємо їх, коли комісія мережі перевищує 4% від суми. diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index fa0fd9a2ea..e77d811c07 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -23,6 +23,8 @@ 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 @@ -555,6 +557,7 @@ 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. @@ -993,7 +996,7 @@ 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 activation process. Please reset cards one by one. + 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! @@ -1326,6 +1329,8 @@ 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 @@ -1805,9 +1810,9 @@ 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 - The amount received, %1$s %2$s was not deposited to Aave. + Your funds are currently supplied to the Aave protocol, but you can manage them at any time. + 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. Approve needed @@ -1817,66 +1822,66 @@ Text about your money in balance [PLACEHOLDER] Your %s is deposited in Aave Unable to load chart... - The amount received, %1$s %2$s was not deposited to Aave. + The amount received, %1$s %2$s was not supplied to Aave. APY %1$s%% Available Current APY - When topping up for lending, a network fee will be deducted from the amount — never more than %1$s + 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 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. + 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 deposit more funds, they\'ll be supplied to Aave to earn interest, minus a transaction fee. Earn Total earnings Transfers to Aave Explore 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. If network fees rise above maximum fee, the transaction won’t go through until they decrease. You can change this limit later. Maximum fee - The transaction fee must stay below 4% of your deposit. Tangem will transfer funds to Aave only once your balance is large enough to meet this condition. - Minimal top-up + This is the lowest amount that can be supplied to Aave. To keep the yield mode profitable, we won’t supply assets when network fees exceed 4% of the amount. + Minimal deposit Fee policy - Tangem also takes a 3% service fee on the yield earned. - Your funds will be automatically transferred to Aave once network fees are lower or your balance meets the minimum required amount. + Tangem also takes a 3% 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 + Token approvals 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 suplied to Aave automatically. + Auto-Transfer to Aave Send, swap, or sell your funds instantly, anytime you want. - Access to funds at any time + Access your funds anytime How it works? Aave is a decentralized protocol managing over $81.9 billion in total value. Decentralized and self-custodial - By using service, you agree with provider\n%1$s and %2$s + 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. + 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 and will stay instantly available + Your %s will be supplied to Aave, but will remain manageable. See fee policy - Your next top-ups will be automatically supplied to Aave. + Your next deposits will be automatically supplied to Aave. Active Paused Disable yield mode - Turning off will withdraw your funds from Aave, return them to %s in your wallet, and stop earning rewards. + Turning this off will withdraw your funds from Aave to %s in your wallet and it will stop earning rewards. The network fee will be deducted from the amount you withdraw. Supply APY APY - Let your funds work in the background while you stay in control. + Let your funds do the work while you stay in control. Interest accrues automatically Yield mode Processing your deposit - Make your balance work for you + Make your assets work for you Automatic Deposit some %1$s %2$s to cover the network fee for transactions Unable to cover %s fee diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrencyChecksRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrencyChecksRepository.kt index 48ac28966a..0d179fc31e 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrencyChecksRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrencyChecksRepository.kt @@ -2,7 +2,6 @@ package com.tangem.data.tokens.repository import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider import com.tangem.blockchain.common.* -import com.tangem.blockchainsdk.utils.toBlockchain import com.tangem.data.tokens.converters.UtxoConverter import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus @@ -19,7 +18,6 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.isZero import com.tangem.utils.extensions.orZero import kotlinx.coroutines.withContext -import timber.log.Timber import java.math.BigDecimal internal class DefaultCurrencyChecksRepository( @@ -168,27 +166,4 @@ internal class DefaultCurrencyChecksRepository( else -> null } } - - override suspend fun getProtocolBalance( - userWalletId: UserWalletId, - cryptoCurrencyStatus: CryptoCurrencyStatus, - ): BigDecimal? { - val token = cryptoCurrencyStatus.currency as? CryptoCurrency.Token ?: return null - val isActive = cryptoCurrencyStatus.value.yieldSupplyStatus?.isActive ?: false - if (!isActive) return null - return runCatching { - val walletManager = walletManagersFacade.getOrCreateWalletManager( - userWalletId = userWalletId, - blockchain = token.network.toBlockchain(), - derivationPath = token.network.derivationPath.value, - ) ?: error("Wallet manager not found") - walletManager.getEffectiveProtocolBalance( - token = Token( - symbol = token.symbol, - contractAddress = token.contractAddress, - decimals = token.decimals, - ), - ) - }.onFailure(Timber::e).getOrThrow() - } } \ No newline at end of file diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyWarning.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyWarning.kt index cb4b78542e..9edbf243da 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyWarning.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyWarning.kt @@ -73,10 +73,4 @@ sealed class CryptoCurrencyWarning { val requiredAmount: BigDecimal, val currencyDecimals: Int, ) : CryptoCurrencyWarning() - - data class YieldSupplyNotDepositedAmount( - val currency: CryptoCurrency, - val currencySymbol: String, - val amount: BigDecimal, - ) : CryptoCurrencyWarning() } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt index d491aff2a6..d4611e9d40 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt @@ -51,8 +51,7 @@ class GetCurrencyWarningsUseCase( flowOf(currencyChecksRepository.getRentInfoWarning(userWalletId, currencyStatus)), flowOf(currencyChecksRepository.getExistentialDeposit(userWalletId, currency.network)), flowOf(currencyChecksRepository.getFeeResourceAmount(userWalletId, currency.network)), - flowOf(currencyChecksRepository.getProtocolBalance(userWalletId, currencyStatus)), - ) { coinRelatedWarnings, maybeRentWarning, maybeEdWarning, maybeFeeResource, yieldSupplyProtocolBalance -> + ) { coinRelatedWarnings, maybeRentWarning, maybeEdWarning, maybeFeeResource -> setOfNotNull( maybeRentWarning, maybeEdWarning?.let { getExistentialDepositWarning(currency, it) }, @@ -63,7 +62,6 @@ class GetCurrencyWarningsUseCase( getBeaconChainShutdownWarning(rawId = currency.network.id.rawId), getAssetRequirementsWarning(userWalletId = userWalletId, currency = currency), getMigrationFromMaticToPolWarning(currency), - getYieldSupplyWarning(cryptoCurrencyStatus = currencyStatus, yieldSupplyProtocolBalance), ) }.flowOn(dispatchers.io) } @@ -263,28 +261,6 @@ class GetCurrencyWarningsUseCase( } } - private fun getYieldSupplyWarning( - cryptoCurrencyStatus: CryptoCurrencyStatus, - protocolBalance: BigDecimal?, - ): CryptoCurrencyWarning? { - val value = cryptoCurrencyStatus.value - val isActive = value.yieldSupplyStatus?.isActive == true - val amount = value.amount - - if (!isActive || protocolBalance == null || amount == null) return null - - val notDepositedAmount = amount.minus(protocolBalance) - return if (notDepositedAmount > BigDecimal.ZERO) { - CryptoCurrencyWarning.YieldSupplyNotDepositedAmount( - currency = cryptoCurrencyStatus.currency, - amount = notDepositedAmount, - currencySymbol = cryptoCurrencyStatus.currency.symbol, - ) - } else { - null - } - } - private fun BigDecimal?.isZero(): Boolean { return this?.signum() == 0 } diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrencyChecksRepository.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrencyChecksRepository.kt index d1b4b99d81..8351958b10 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrencyChecksRepository.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrencyChecksRepository.kt @@ -61,11 +61,4 @@ interface CurrencyChecksRepository { currencyStatus: CryptoCurrencyStatus, balanceAfterTransaction: BigDecimal, ): CryptoCurrencyWarning.Rent? - - /** - * Returns the YieldSupplied protocol balance in Aave for the given `cryptoCurrency`. - * This represents the amount supplied to the protocol for the specified `userWalletId` - * (e.g., aTokens balance). Returns null if not applicable or unknown. - */ - suspend fun getProtocolBalance(userWalletId: UserWalletId, cryptoCurrencyStatus: CryptoCurrencyStatus): BigDecimal? } \ No newline at end of file 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 e463368cd3..3c8c7aa671 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 @@ -4,6 +4,7 @@ import arrow.core.Either import arrow.core.Either.Companion.catch 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.quote.QuoteStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.quotes.QuotesRepository @@ -51,7 +52,9 @@ class YieldSupplyGetMaxFeeUseCase( ?: error("Native fiat rate is missing") require(nativeFiatRate > BigDecimal.ZERO) { "Native fiat rate must be > 0" } - val marketToken = yieldSupplyRepository.getTokenStatus(token) + val cachedMarketToken = yieldSupplyRepository.getCachedMarkets().orEmpty() + .firstOrNull { it.yieldSupplyKey == token.yieldSupplyKey() } + val marketToken = cachedMarketToken ?: yieldSupplyRepository.getTokenStatus(token) val maxFeeNative = marketToken.maxFeeNative.toBigDecimal() val rateRatio = nativeFiatRate.divide( diff --git a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/entity/TokenReceiveStateFactory.kt b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/entity/TokenReceiveStateFactory.kt index 2d014adf53..ee3dd1a028 100644 --- a/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/entity/TokenReceiveStateFactory.kt +++ b/features/token-recieve/impl/src/main/java/com/tangem/features/tokenreceive/entity/TokenReceiveStateFactory.kt @@ -19,7 +19,6 @@ import com.tangem.features.tokenreceive.entity.ReceiveAddress.Type.Ens import com.tangem.features.tokenreceive.entity.ReceiveAddress.Type.Primary import com.tangem.features.tokenreceive.ui.state.TokenReceiveUM import com.tangem.utils.Provider -import com.tangem.utils.extensions.addIf import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toPersistentList @@ -138,12 +137,7 @@ internal class TokenReceiveStateFactory( tokenName: String, tokenReceiveNotification: List, ): List { - val yieldSupplyNotification: TokenReceiveNotification? = - tokenReceiveNotification.firstOrNull { it.isYieldSupplyNotification } return buildList { - addIf(yieldSupplyNotification != null) { - NotificationUM.Warning.YieldSupplyIsActive(tokenName) - } add( NotificationUM.Info( title = resourceReference( diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt index c5081a966c..dfb37410b9 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt @@ -156,10 +156,6 @@ internal class TokenDetailsNotificationConverter( ) is CryptoCurrencyWarning.MigrationMaticToPol -> MigrationMaticToPol is CryptoCurrencyWarning.UsedOutdatedDataWarning -> UsedOutdatedData - is CryptoCurrencyWarning.YieldSupplyNotDepositedAmount -> YieldSupplyNotTransferedToAave( - tokenName = warning.currencySymbol, - amount = warning.amount.format { crypto(symbol = "", decimals = warning.currency.decimals) }, - ) } } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/entity/YieldSupplyUM.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/entity/YieldSupplyUM.kt index 112b1dbb24..2d7419ea4b 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/entity/YieldSupplyUM.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/entity/YieldSupplyUM.kt @@ -24,7 +24,7 @@ internal sealed class YieldSupplyUM { val subtitle: TextReference, val rewardsApy: TextReference, val onClick: () -> Unit, - val isAllowedToSpend: Boolean, + val showWarningIcon: Boolean, ) : YieldSupplyUM() @Immutable diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt index 5d1d974638..70ab6a6a95 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt @@ -15,6 +15,7 @@ import com.tangem.core.ui.extensions.stringReference import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.currency.yieldSupplyNotAllAmountSupplied import com.tangem.domain.models.network.TxInfo import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.yield.supply.YieldSupplyStatus @@ -238,28 +239,29 @@ internal class YieldSupplyModel @Inject constructor( } } yieldSupplyStatus?.isActive == true -> { - val cryptoCurrencyToken = cryptoCurrency as? CryptoCurrency.Token ?: return - if (!yieldSupplyStatus.isAllowedToSpend) { - analyticsEventsHandler.send( - YieldSupplyAnalytics.NoticeApproveNeeded( - token = cryptoCurrency.symbol, - blockchain = cryptoCurrency.network.name, - ), - ) - } loadActiveState( - cryptoCurrencyToken = cryptoCurrencyToken, + cryptoCurrencyStatus = cryptoCurrencyStatus, yieldSupplyStatus = yieldSupplyStatus, ) } - else -> { loadTokenStatus() } } } - private fun loadActiveState(cryptoCurrencyToken: CryptoCurrency.Token, yieldSupplyStatus: YieldSupplyStatus) { + private fun loadActiveState(cryptoCurrencyStatus: CryptoCurrencyStatus, yieldSupplyStatus: YieldSupplyStatus) { + val cryptoCurrencyToken = cryptoCurrency as? CryptoCurrency.Token ?: return + val showWarningIcon = !yieldSupplyStatus.isAllowedToSpend || + cryptoCurrencyStatus.yieldSupplyNotAllAmountSupplied() + if (!yieldSupplyStatus.isAllowedToSpend) { + analyticsEventsHandler.send( + YieldSupplyAnalytics.NoticeApproveNeeded( + token = cryptoCurrency.symbol, + blockchain = cryptoCurrency.network.name, + ), + ) + } modelScope.launch(dispatchers.default) { yieldSupplyGetTokenStatusUseCase(cryptoCurrencyToken) .onRight { tokenStatus -> @@ -278,7 +280,7 @@ internal class YieldSupplyModel @Inject constructor( stringReference(" ${tokenStatus.apy}%"), ), onClick = ::onActiveClick, - isAllowedToSpend = yieldSupplyStatus.isAllowedToSpend, + showWarningIcon = showWarningIcon, apy = tokenStatus.apy.toString(), ) } @@ -294,7 +296,7 @@ internal class YieldSupplyModel @Inject constructor( ), rewardsApy = TextReference.EMPTY, onClick = ::onActiveClick, - isAllowedToSpend = yieldSupplyStatus.isAllowedToSpend, + showWarningIcon = showWarningIcon, apy = "", ) } 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 49ea1ef511..913def042b 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 @@ -132,7 +132,7 @@ private fun SupplyContent(supplyUM: YieldSupplyUM.Content) { ) } SpacerW8() - AnimatedVisibility(supplyUM.isAllowedToSpend.not()) { + AnimatedVisibility(supplyUM.showWarningIcon) { Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_alert_triangle_20), contentDescription = null, @@ -317,7 +317,7 @@ private class PreviewProvider : PreviewParameterProvider { rewardsApy = stringReference("5.1 % APY"), onClick = {}, apy = "5.1", - isAllowedToSpend = false, + showWarningIcon = false, ), YieldSupplyUM.Content( title = stringReference("Aave lending is active"), @@ -325,7 +325,7 @@ private class PreviewProvider : PreviewParameterProvider { rewardsApy = stringReference("5.1 % APY"), onClick = {}, apy = "5.1", - isAllowedToSpend = true, + showWarningIcon = true, ), YieldSupplyUM.Loading, YieldSupplyUM.Processing.Enter, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/YieldSupplyActiveComponent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/YieldSupplyActiveComponent.kt index db0f137890..0dccc9df82 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/YieldSupplyActiveComponent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/YieldSupplyActiveComponent.kt @@ -50,6 +50,7 @@ internal class YieldSupplyActiveComponent( state = state, isBalanceHidden = isBalanceHidden, chartComponent = chartComponent, + onReadMoreClick = params.callback::onReadMoreClick, modifier = Modifier, ) } @@ -76,5 +77,6 @@ internal class YieldSupplyActiveComponent( fun onBackClick() fun onStopEarning() fun onApprove() + fun onReadMoreClick() } } \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt index 9b93df6c2a..2e7b5c14dc 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt @@ -2,6 +2,7 @@ package com.tangem.features.yield.supply.impl.subcomponents.active.entity import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.ui.extensions.TextReference +import kotlinx.collections.immutable.ImmutableList internal data class YieldSupplyActiveContentUM( val totalEarnings: TextReference, @@ -9,7 +10,7 @@ internal data class YieldSupplyActiveContentUM( val providerTitle: TextReference, val subtitle: TextReference, val subtitleLink: TextReference, - val notificationUM: NotificationUM?, + val notifications: ImmutableList, val minAmount: TextReference?, val currentFee: TextReference?, val feeDescription: TextReference?, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveEntryModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveEntryModel.kt index 1d60926512..02fc956678 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveEntryModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveEntryModel.kt @@ -4,10 +4,12 @@ import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router +import com.tangem.core.navigation.url.UrlOpener import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyActiveComponent import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyActiveEntryComponent import com.tangem.features.yield.supply.impl.subcomponents.approve.YieldSupplyApproveComponent import com.tangem.features.yield.supply.impl.subcomponents.stopearning.YieldSupplyStopEarningComponent +import com.tangem.utils.TangemBlogUrlBuilder import com.tangem.utils.coroutines.CoroutineDispatcherProvider import javax.inject.Inject @@ -16,6 +18,7 @@ internal class YieldSupplyActiveEntryModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, paramsContainer: ParamsContainer, private val router: Router, + private val urlOpener: UrlOpener, ) : Model(), YieldSupplyActiveComponent.ModelCallback, YieldSupplyStopEarningComponent.ModelCallback, YieldSupplyApproveComponent.ModelCallback { @@ -37,4 +40,8 @@ internal class YieldSupplyActiveEntryModel @Inject constructor( override fun onApprove() { router.push(YieldSupplyActiveRoute.Approve) } + + override fun onReadMoreClick() { + urlOpener.openUrl(TangemBlogUrlBuilder.YIELD_SUPPLY_HOW_IT_WORKS_URL) + } } \ No newline at end of file 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 a74719003c..42617b38f5 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 @@ -17,6 +17,7 @@ import com.tangem.core.ui.format.bigdecimal.format 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.yield.supply.usecase.YieldSupplyGetProtocolBalanceUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyMinAmountUseCase @@ -29,9 +30,13 @@ import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyAct import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM import com.tangem.utils.StringsSigns.DASH_SIGN import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import timber.log.Timber +import java.math.BigDecimal import javax.inject.Inject @Suppress("LongParameterList") @@ -65,7 +70,7 @@ internal class YieldSupplyActiveModel @Inject constructor( formatArgs = wrappedList(cryptoCurrency.symbol, cryptoCurrency.symbol), ), subtitleLink = resourceReference(R.string.common_read_more), - notificationUM = null, + notifications = persistentListOf(), minAmount = null, currentFee = null, feeDescription = null, @@ -108,27 +113,13 @@ internal class YieldSupplyActiveModel @Inject constructor( cryptoCurrency = cryptoCurrency, ).getOrNull() - val approvalNotification = if (cryptoCurrencyStatus.value.yieldSupplyStatus?.isAllowedToSpend != true) { - NotificationUM.Error( - title = resourceReference(R.string.yield_module_approve_needed_notification_title), - subtitle = resourceReference(R.string.yield_module_approve_needed_notification_description), - iconResId = R.drawable.ic_alert_triangle_20, - buttonState = NotificationConfig.ButtonsState.PrimaryButtonConfig( - text = resourceReference(R.string.yield_module_approve_needed_notification_cta), - onClick = params.callback::onApprove, - ), - ) - } else { - null - } - loadApy() loadMinAmount() loadFees() uiState.update { it.copy( - notificationUM = approvalNotification, + notifications = getNotifications(cryptoCurrencyStatus), availableBalance = stringReference( protocolBalance.format { crypto( @@ -153,11 +144,58 @@ internal class YieldSupplyActiveModel @Inject constructor( ) } }.onLeft { + uiState.update { + it.copy( + apy = TextReference.Str(DASH_SIGN), + ) + } Timber.e("Error loading token status") } } } + private fun getNotifications(cryptoCurrencyStatus: CryptoCurrencyStatus): ImmutableList { + val approvalNotification = if (cryptoCurrencyStatus.value.yieldSupplyStatus?.isAllowedToSpend != true) { + NotificationUM.Error( + title = resourceReference(R.string.yield_module_approve_needed_notification_title), + subtitle = resourceReference(R.string.yield_module_approve_needed_notification_description), + iconResId = R.drawable.ic_alert_triangle_20, + buttonState = NotificationConfig.ButtonsState.PrimaryButtonConfig( + text = resourceReference(R.string.yield_module_approve_needed_notification_cta), + onClick = params.callback::onApprove, + ), + ) + } else { + null + } + val notSuppliedNotification = getNotSuppliedNotification(cryptoCurrencyStatus) + return listOfNotNull( + approvalNotification, + notSuppliedNotification, + ).toPersistentList() + } + + private fun getNotSuppliedNotification(cryptoCurrencyStatus: CryptoCurrencyStatus): NotificationUM? { + val value = cryptoCurrencyStatus.value + val isActive = value.yieldSupplyStatus?.isActive == true + val effectiveProtocolBalance = value.yieldSupplyStatus?.effectiveProtocolBalance ?: null + val amount = value.amount + + if (!isActive || effectiveProtocolBalance == null || amount == null) return null + + val notDepositedAmount = amount.minus(effectiveProtocolBalance) + return if (notDepositedAmount > BigDecimal.ZERO) { + val formattedAmount = + notDepositedAmount.format { crypto(symbol = "", decimals = cryptoCurrencyStatus.currency.decimals) } + NotificationUM.Warning.YieldSupplyNotAllAmountSupplied( + formattedAmount = formattedAmount, + symbol = cryptoCurrency.symbol, + ) + } else { + null + } + } + private fun loadMinAmount() { modelScope.launch(dispatchers.default) { yieldSupplyMinAmountUseCase( diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt index 9e2346fe2f..867fdefd59 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt @@ -28,17 +28,20 @@ import androidx.compose.ui.unit.dp import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.ui.components.* import com.tangem.core.ui.components.notifications.Notification +import com.tangem.core.ui.components.notifications.NotificationConfig import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.core.ui.extensions.* import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM +import kotlinx.collections.immutable.persistentListOf @Composable internal fun YieldSupplyActiveContent( state: YieldSupplyActiveContentUM, isBalanceHidden: Boolean, + onReadMoreClick: () -> Unit, chartComponent: ComposableContentComponent, modifier: Modifier = Modifier, ) { @@ -61,16 +64,23 @@ internal fun YieldSupplyActiveContent( chartComponent.Content(Modifier.padding(bottom = 12.dp)) } - AnimatedVisibility(state.notificationUM != null) { - val wrappedNotification = remember(this) { requireNotNull(state.notificationUM) } - Notification( - config = wrappedNotification.config, - iconTint = null, - containerColor = TangemTheme.colors.background.action, - ) + AnimatedVisibility(state.notifications.isNotEmpty()) { + val notifications = remember(state.notifications) { state.notifications } + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + notifications.forEach { notificationUM -> + Notification( + config = notificationUM.config, + containerColor = TangemTheme.colors.background.action, + ) + } + } } - YieldSupplyActiveMyFunds(state = state, isBalanceHidden = isBalanceHidden) + YieldSupplyActiveMyFunds( + state = state, + isBalanceHidden = isBalanceHidden, + onReadMoreClick = onReadMoreClick, + ) AnimatedVisibility(state.feeDescription != null) { Text( @@ -108,7 +118,7 @@ private fun CurrentApy(apy: TextReference?, modifier: Modifier = Modifier) { TextShimmer( modifier = modifier.width(94.dp), text = "", - style = TangemTheme.typography.head, + style = TangemTheme.typography.h2, ) } else { Row(verticalAlignment = Alignment.CenterVertically) { @@ -123,7 +133,7 @@ private fun CurrentApy(apy: TextReference?, modifier: Modifier = Modifier) { Text( modifier = modifier, text = apyText, - style = TangemTheme.typography.body1, + style = TangemTheme.typography.h2, color = TangemTheme.colors.text.accent, ) } @@ -134,7 +144,11 @@ private fun CurrentApy(apy: TextReference?, modifier: Modifier = Modifier) { @Suppress("LongMethod") @Composable -private fun YieldSupplyActiveMyFunds(state: YieldSupplyActiveContentUM, isBalanceHidden: Boolean) { +private fun YieldSupplyActiveMyFunds( + state: YieldSupplyActiveContentUM, + onReadMoreClick: () -> Unit, + isBalanceHidden: Boolean, +) { Column( modifier = Modifier .clip(RoundedCornerShape(16.dp)) @@ -164,7 +178,7 @@ private fun YieldSupplyActiveMyFunds(state: YieldSupplyActiveContentUM, isBalanc ) } SpacerH8() - DescriptionText(state = state) + DescriptionText(state = state, onReadMoreClick = onReadMoreClick) SpacerH8() HorizontalDivider( thickness = 0.5.dp, @@ -206,14 +220,14 @@ private fun YieldSupplyActiveMyFunds(state: YieldSupplyActiveContentUM, isBalanc } @Composable -private fun DescriptionText(state: YieldSupplyActiveContentUM) { +private fun DescriptionText(state: YieldSupplyActiveContentUM, onReadMoreClick: () -> Unit) { val subtitle = annotatedReference { append(state.subtitle.resolveReference()) appendSpace() withLink( LinkAnnotation.Clickable( tag = "LINK_TAG", - linkInteractionListener = {}, + linkInteractionListener = { onReadMoreClick() }, ), { appendColored( @@ -324,6 +338,7 @@ private fun YieldSupplyActiveBottomSheet_Preview( state = params, isBalanceHidden = true, chartComponent = ComposableContentComponent.EMPTY, + onReadMoreClick = {}, ) } } @@ -340,15 +355,27 @@ private class YieldSupplyActiveBottomSheetPreviewProvider : PreviewParameterProv wrappedList("USDT", "USDT"), ), subtitleLink = resourceReference(R.string.common_read_more), - notificationUM = NotificationUM.Error.InvalidAmount, - apy = stringReference("5,14%"), + notifications = persistentListOf( + NotificationUM.Error.InvalidAmount, + NotificationUM.Info( + title = resourceReference( + R.string.yield_module_amount_not_transfered_to_aave_title, + wrappedList( + "0,03", + ), + ), + subtitle = TextReference.EMPTY, + iconTint = NotificationConfig.IconTint.Accent, + ), + ), minAmount = stringReference("50 USDT"), - isHighFee = true, + currentFee = stringReference("30 USDT"), feeDescription = stringReference( "The network fee is currently too high to execute lending." + "Funds will be supplied once it drops to \$12 or below. ", ), - currentFee = stringReference("30 USDT"), + apy = stringReference("5,14%"), + isHighFee = true, ), ) } From aa6f185cd1123f3886edf45ce08653587ed715e8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 22 Oct 2025 22:05:13 +0500 Subject: [PATCH 04/13] Updated on 2026-08-14 --- core/res/src/main/res/values-es/strings.xml | 2 + core/res/src/main/res/values-fr/strings.xml | 3 + core/res/src/main/res/values-ja/strings.xml | 45 +++--- core/res/src/main/res/values-ru/strings.xml | 1 + .../src/main/res/values-uk-rUA/strings.xml | 2 + core/res/src/main/res/values/strings.xml | 9 +- .../impl/common/entity/YieldSupplyFeeUM.kt | 10 +- .../common/ui/YieldSupplyActionContent.kt | 17 ++- .../impl/common/ui/YieldSupplyFeeRow.kt | 13 +- .../entity/YieldSupplyActiveContentUM.kt | 1 + .../active/model/YieldSupplyActiveModel.kt | 67 ++++----- .../YieldSupplyActiveFeeContentTransformer.kt | 57 +++++++ .../YieldSupplyActiveMinAmountTransformer.kt | 46 ++++++ .../active/ui/YieldSupplyActiveContent.kt | 18 ++- .../approve/model/YieldSupplyApproveModel.kt | 17 +-- .../YieldSupplyFeePolicyComponent.kt | 1 - .../ui/YieldSupplyFeePolicyContent.kt | 140 ++++++++++-------- ...SupplyStartEarningFeeContentTransformer.kt | 78 +++++----- ...dSupplyStopEarningFeeContentTransformer.kt | 21 +-- 19 files changed, 343 insertions(+), 205 deletions(-) create mode 100644 features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveFeeContentTransformer.kt create mode 100644 features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveMinAmountTransformer.kt diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml index 6a2f5f1caf..98241d95b8 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -1106,6 +1106,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. @@ -1400,6 +1401,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 diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index 868ad2f695..4685df09fe 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -1080,6 +1080,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. @@ -1386,6 +1387,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 @@ -1453,4 +1455,5 @@ 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 + 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). diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index c1f18f6577..68a1c38379 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -23,6 +23,8 @@ アカウントを復元できません アーカイブ済み アカウントをアーカイブできませんでした。しばらくしてからもう一度お試しください。 + このアカウントは紹介プログラムに参加しています。 + このアカウントはアーカイブできません。 アカウントを作成できませんでした。しばらくしてからもう一度お試しください。 アカウントを作成しました アカウントをアーカイブする @@ -42,6 +44,8 @@ アカウントを編集 %1$s ( %2$s内) メインアカウント + すでにアクティブアカウントの上限%1$s件を超えています。復元するには、1つをアーカイブしてください。 + アカウントを復元できません アカウントが回復しました アカウントを長押しして並べ替える 編集を続ける @@ -546,6 +550,7 @@ その他の方法 秘密鍵をオフラインで安全に保存する物理デバイス。 リカバリーフレーズ + ウォレットをハードウェアにアップグレードするには、まずバックアップしてください。 鍵はアプリに保存されます シードフレーズのバックアップ モバイルウォレットを作成する @@ -1303,6 +1308,8 @@ この手数料は、送金処理にかかるコストをカバーするためのものです。 出金 PINを変更する + カードは支払いの準備が整いました。 + PINコードを作成しました データの読み込みに失敗しました。しばらくしてからもう一度お試しください。 カードの一時停止 非表示 @@ -1733,8 +1740,9 @@ いいえ、すべて送信します %s XTZを減らす 次回ウォレットにチャージするときに手数料の増加を避けるには、金額を%s XTZ減らしてください。 - %sはAaveに預けられています - 受け取った金額%1$s %2$sはAaveに入金されませんでした。 + あなたの資金は現在Aaveプロトコルに供給されていますが、いつでも管理できます。 + %sはAaveに供給されています + Aaveへの%1$s %2$sの供給は保留中です 承認する 前回の承認に問題があったため、新しい承認が必要です。手続き方法を選択してください。 承認が必要 @@ -1748,62 +1756,63 @@ 年利%1$s%% 利用可能 現在のAPY - 貸付のためにチャージする際は、ネットワーク手数料が金額から差し引かれます(手数料は常に%1$s以下です)。 + 貸付のために入金する際は、残高から%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%未満である必要があります。残高がこの条件を満たすのに十分な金額になった場合にのみ、TangemはAaveに資金を送ります。 + 最小金額は現在のネットワーク手数料に基づいて計算されており、手数料が4%を超えないように設定されています。その結果、最小金額は%1$s(%2$s)となります。 最低入金額 手数料ポリシー Tangemはまた、得られた利回りに対して3%のサービス手数料を差し引きます。 - ネットワーク手数料が下がるか、残高が必要な最低額に達すると、自動的にAaveへ送金されます。 + ネットワーク手数料が下がるか、残高が最低必要額に達すると、資金は自動的にAaveに供給されます。 過去のリターン ここに説明を入力してください。1〜3行が理想的です。[プレースホルダー] - トークン承認が必要 + トークンの承認が必要 ネットワーク接続を確認してください ネットワーク手数料についての情報にアクセスできません - アカウントへの入金はすべて自動的にAaveに貸し出されます。 - 残高は自動的に計算されます + あなたが行うすべての入金は、自動的にAaveへ供給されます。 + Aaveへの自動送金 いつでも、即座に資金を送信、交換、売却できます。 いつでも資金にアクセス可能 使い方 Aaveは、総額819億ドル以上の資産を管理する分散型プロトコルです。 分散型・自己管理型 - サービスを利用することにより、プロバイダー\n %1$sおよび%2$sに同意したことになります + このサービスを利用することにより、プロバイダー\n%1$sおよび%2$sに同意するものとします。 Aave を接続 Aave %1$s%% • 変動金利 Aave 平均%s 昨年のリターン - 現在の金利は常に変動し、リアルタイムの需要と供給に基づいて、AAVEオンチェーンスマートコントラクトによって自動的に計算されます。 + 現在の金利は常に変動し、リアルタイムの需要と供給に基づいて、Aaveオンチェーンスマートコントラクトによって自動的に計算されます。 提供 金利は変動します - 入金すると、資金は自動的にAaveに送金され、利息が付き始めます。取引手数料として%s相当の少額の手数料が差し引かれます。 + 入金すると、資金は自動的にAaveに送金され、利息が付き始めます。%sが取引手数料として差し引かれます。 資産を供給する - %sはAaveに供給され、すぐに利用可能になります + %sはAaveに供給されますが、管理可能な状態のままになります。 手数料ポリシーを見る - 次回以降の入金は自動的にAaveに供給されます。 + 次回の入金は自動的にAaveに供給されます。 アクティブ 停止中 利回りモードを無効にする - オフにすると、Aaveから資金が引き出され、ウォレットの%sに戻され、報酬の獲得が停止されます。 + これをオフにすると、Aave からウォレットの %s に資金が引き出され、報酬の獲得が停止します。 出金金額からネットワーク手数料が差し引かれます。 供給APY APY - 自分で管理しながら、資金をバックグラウンドで運用しましょう。 + 自分で管理しながら、資金に働かせましょう。 利息は自動的に発生します 利回りモード 入金の処理中 - 残高を活用 + 資産を有効活用しましょう 自動 取引のネットワーク手数料をカバーするために、 %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 9b73434b2d..9f8d33a4a4 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -1494,6 +1494,7 @@ Похоже, возникла проблема Все dapps отключены Разрешение на использование + Подтверждая, вы разрешаете смарт-контракту использовать ваши токены в будущих транзакциях. Адрес Подключение Загрузка 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 b13f5ecb1d..ef07e28698 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -1086,6 +1086,7 @@ Web 3.0 сумісність Для відправки потрібна вхідна транзакція на суму не менше %1$s Недостатньо коштів + Підтверджуючи, ви дозволяєте смартконтракту використовувати ваші токени в майбутніх транзакціях. Мережа стягує комісію за схвалення токену за підтвердження, що саме ви дозволяєте використовувати ваш токен для обміну. Обмінюйте більше токенів за вигіднішим курсом прямо у своєму гаманці. З\'явився новий провайдер обмінів! @@ -1366,6 +1367,7 @@ Обрана не вірна картка або кільце Схоже, виникла проблема Усі dApps відключені + Підтверджуючи, ви дозволяєте dApp або смартконтракту використовувати токени в майбутніх транзакціях. Адреса Підключення Мережа diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index e77d811c07..5015abed71 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -44,6 +44,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 @@ -1837,10 +1839,11 @@ This is the current supply fee on %s. The actual cost will be shown on the activation tab. Current fee 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 - This is the lowest amount that can be supplied to Aave. To keep the yield mode profitable, we won’t supply assets when network fees exceed 4% of the amount. - Minimal deposit + 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 Tangem also takes a 3% 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. @@ -1849,7 +1852,7 @@ Token approvals needed Check your network connection Network fee info unreachable - Every deposit you make will be suplied to Aave 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. Access your funds anytime 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 ffac0fef60..7b3d8e94ed 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 @@ -13,10 +13,12 @@ internal sealed class YieldSupplyFeeUM { data object Error : YieldSupplyFeeUM() data class Content( val transactionDataList: ImmutableList, - val feeValue: TextReference, - val currentNetworkFeeValue: TextReference, - val maxNetworkFeeValue: TextReference, - val minAmountFeeValue: TextReference, + val feeFiatValue: TextReference, + val tokenFeeFiatValue: TextReference, + val maxNetworkFeeFiatValue: TextReference, + val minTopUpFiatValue: TextReference, + val feeNoteValue: TextReference = TextReference.EMPTY, + val minFeeNoteValue: TextReference = TextReference.EMPTY, ) : YieldSupplyFeeUM() } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt index 03437a23fe..abc8b25b63 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt @@ -3,11 +3,13 @@ package com.tangem.features.yield.supply.impl.common.ui import android.content.res.Configuration import androidx.compose.foundation.background import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.key import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.text.LinkAnnotation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.withLink @@ -85,13 +87,17 @@ internal fun YieldSupplyActionContent( ), ) { val fee = when (val yieldSupplyFeeUM = yieldSupplyActionUM.yieldSupplyFeeUM) { - is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.feeValue + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.feeFiatValue YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) YieldSupplyFeeUM.Loading -> null } YieldSupplyFeeRow( title = resourceReference(R.string.common_network_fee_title), value = fee, + modifier = Modifier.fillMaxWidth() + .clip(RoundedCornerShape(14.dp)) + .background(TangemTheme.colors.background.action) + .padding(horizontal = 16.dp, vertical = 12.dp), ) } } @@ -138,10 +144,11 @@ private class YieldSupplyActionContentPreviewProvider : PreviewParameterProvider currencyIconState = CurrencyIconState.Loading, yieldSupplyFeeUM = YieldSupplyFeeUM.Content( transactionDataList = persistentListOf(), - feeValue = stringReference("0.00020 ETH • \$0.99"), - currentNetworkFeeValue = stringReference("1.45 USDT • \$1.45"), - maxNetworkFeeValue = stringReference("8.50 USDT • \$8.50"), - minAmountFeeValue = stringReference("50 USDT • \$50"), + feeFiatValue = stringReference("$0.99"), + tokenFeeFiatValue = stringReference("$1.45"), + maxNetworkFeeFiatValue = stringReference("$8.50"), + minTopUpFiatValue = stringReference("$50"), + feeNoteValue = TextReference.EMPTY, ), isPrimaryButtonEnabled = false, isTransactionSending = false, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyFeeRow.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyFeeRow.kt index dc00a547a8..c893885dbb 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyFeeRow.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyFeeRow.kt @@ -1,17 +1,12 @@ package com.tangem.features.yield.supply.impl.common.ui import androidx.compose.animation.AnimatedContent -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.tangem.core.ui.components.SpacerWMax @@ -23,15 +18,11 @@ import com.tangem.core.ui.res.TangemTheme import com.tangem.features.yield.supply.impl.R @Composable -internal fun YieldSupplyFeeRow(title: TextReference, value: TextReference?) { +internal fun YieldSupplyFeeRow(title: TextReference, value: TextReference?, modifier: Modifier = Modifier) { Row( horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(14.dp)) - .background(TangemTheme.colors.background.action) - .padding(horizontal = 16.dp, vertical = 12.dp), + modifier = modifier, ) { Text( text = title.resolveReference(), diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt index 2e7b5c14dc..eea128679c 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/entity/YieldSupplyActiveContentUM.kt @@ -14,6 +14,7 @@ internal data class YieldSupplyActiveContentUM( val minAmount: TextReference?, val currentFee: TextReference?, val feeDescription: TextReference?, + val minFeeDescription: TextReference?, val apy: TextReference? = null, val isHighFee: Boolean = false, ) \ No newline at end of file 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 42617b38f5..8d8bd96071 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 @@ -12,7 +12,6 @@ import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.format.bigdecimal.crypto -import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.format import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency @@ -25,11 +24,13 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyGetCurrentFeeUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyGetMaxFeeUseCase import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics import com.tangem.features.yield.supply.impl.R -import com.tangem.features.yield.supply.impl.common.formatter.YieldSupplyAmountFormatter import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyActiveComponent import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM +import com.tangem.features.yield.supply.impl.subcomponents.active.model.transformers.YieldSupplyActiveMinAmountTransformer +import com.tangem.features.yield.supply.impl.subcomponents.active.model.transformers.YieldSupplyActiveFeeContentTransformer import com.tangem.utils.StringsSigns.DASH_SIGN import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.transformer.update import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList @@ -75,6 +76,7 @@ internal class YieldSupplyActiveModel @Inject constructor( currentFee = null, feeDescription = null, isHighFee = false, + minFeeDescription = null, ), ) @@ -202,20 +204,19 @@ internal class YieldSupplyActiveModel @Inject constructor( params.userWallet, cryptoCurrencyStatusFlow.value, ).onRight { minAmount -> - val minAmountTextReference = YieldSupplyAmountFormatter( - cryptoCurrencyStatusFlow.value.currency, - appCurrency, - ).invoke( - feeValue = minAmount, - fiatRate = cryptoCurrencyStatusFlow.value.value.fiatRate, - showCrypto = false, + uiState.update( + YieldSupplyActiveMinAmountTransformer( + cryptoCurrencyStatus = cryptoCurrencyStatusFlow.value, + appCurrency = appCurrency, + minAmount = minAmount, + ), ) - uiState.update { - it.copy(minAmount = minAmountTextReference) - } }.onLeft { uiState.update { - it.copy(minAmount = TextReference.Str(DASH_SIGN)) + it.copy( + minAmount = TextReference.Str(DASH_SIGN), + feeDescription = null, + ) } } } @@ -235,33 +236,23 @@ internal class YieldSupplyActiveModel @Inject constructor( cryptoCurrencyStatus = cryptoStatus, ).getOrNull() - val currentFeeText = currentFee?.let { - YieldSupplyAmountFormatter( - cryptoStatus.currency, - appCurrency, - ).invoke( - feeValue = it, - fiatRate = cryptoStatus.value.fiatRate, - showCrypto = false, + if (currentFee != null && maxFee != null) { + uiState.update( + YieldSupplyActiveFeeContentTransformer( + cryptoCurrencyStatus = cryptoStatus, + appCurrency = appCurrency, + feeValue = currentFee, + maxNetworkFee = maxFee, + ), ) - } - - val isHighFee = if (currentFee != null && maxFee != null) currentFee > maxFee else false - - val maxFiatFee = maxFee?.multiply(cryptoStatus.value.fiatRate) - .format { fiat(appCurrency.code, appCurrency.symbol) } - val feeDescription = if (isHighFee) { - resourceReference(R.string.yield_module_earn_sheet_high_fee_description, wrappedList(maxFiatFee)) } else { - resourceReference(R.string.yield_module_earn_sheet_fee_description, wrappedList(maxFiatFee)) - } - - uiState.update { - it.copy( - currentFee = currentFeeText ?: stringReference(DASH_SIGN), - isHighFee = isHighFee, - feeDescription = feeDescription, - ) + uiState.update { + it.copy( + currentFee = stringReference(DASH_SIGN), + feeDescription = null, + isHighFee = false, + ) + } } } } 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 new file mode 100644 index 0000000000..bcd2e22076 --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveFeeContentTransformer.kt @@ -0,0 +1,57 @@ +package com.tangem.features.yield.supply.impl.subcomponents.active.model.transformers + +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.format.bigdecimal.crypto +import com.tangem.core.ui.format.bigdecimal.fiat +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.impl.R +import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM +import com.tangem.utils.transformer.Transformer +import java.math.BigDecimal + +/** + * Computes fee description and current fee values for Active screen based on token rates. + */ +internal class YieldSupplyActiveFeeContentTransformer( + private val cryptoCurrencyStatus: CryptoCurrencyStatus, + private val appCurrency: AppCurrency, + private val feeValue: BigDecimal, + private val maxNetworkFee: BigDecimal, +) : Transformer { + + override fun transform(prevState: YieldSupplyActiveContentUM): YieldSupplyActiveContentUM { + val cryptoCurrency = cryptoCurrencyStatus.currency + val tokenFiatRate = cryptoCurrencyStatus.value.fiatRate + + val tokenCryptoFeeValueText = feeValue.format { crypto(cryptoCurrency) } + val tokenFiatFee = tokenFiatRate?.let(feeValue::multiply) + val tokenFiatFeeValueText = tokenFiatFee.format { fiat(appCurrency.code, appCurrency.symbol) } + + val maxFeeCryptoValueText = maxNetworkFee.format { crypto(cryptoCurrency) } + val maxFiatFee = tokenFiatRate?.let { rate -> maxNetworkFee.multiply(rate) } + val maxFiatFeeValueText = maxFiatFee.format { fiat(appCurrency.code, appCurrency.symbol) } + + val feeNoteValue: TextReference = resourceReference( + id = R.string.yield_module_fee_policy_sheet_fee_note, + formatArgs = wrappedList( + stringReference(tokenFiatFeeValueText), + stringReference(tokenCryptoFeeValueText), + stringReference(maxFiatFeeValueText), + stringReference(maxFeeCryptoValueText), + ), + ) + + val isHighFee = feeValue > maxNetworkFee + + return prevState.copy( + currentFee = stringReference(tokenFiatFeeValueText), + feeDescription = feeNoteValue, + isHighFee = isHighFee, + ) + } +} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveMinAmountTransformer.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveMinAmountTransformer.kt new file mode 100644 index 0000000000..91fa089b91 --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveMinAmountTransformer.kt @@ -0,0 +1,46 @@ +package com.tangem.features.yield.supply.impl.subcomponents.active.model.transformers + +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.format.bigdecimal.crypto +import com.tangem.core.ui.format.bigdecimal.fiat +import com.tangem.core.ui.format.bigdecimal.format +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +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 +import java.math.BigDecimal + +/** + * Computes and sets minimum amount (fiat) and fee description note + */ +internal class YieldSupplyActiveMinAmountTransformer( + private val cryptoCurrencyStatus: CryptoCurrencyStatus, + private val appCurrency: AppCurrency, + private val minAmount: BigDecimal, +) : Transformer { + + override fun transform(prevState: YieldSupplyActiveContentUM): YieldSupplyActiveContentUM { + val cryptoCurrency = cryptoCurrencyStatus.currency + val tokenFiatRate = cryptoCurrencyStatus.value.fiatRate + + val minAmountCryptoText = minAmount.format { crypto(cryptoCurrency) } + val minAmountFiat = tokenFiatRate?.let(minAmount::multiply) + val minAmountFiatText = minAmountFiat.format { fiat(appCurrency.code, appCurrency.symbol) } + + val minFeeNoteValue = resourceReference( + id = R.string.yield_module_fee_policy_sheet_min_amount_note, + formatArgs = wrappedList( + minAmountFiatText, + minAmountCryptoText, + ), + ) + + return prevState.copy( + minAmount = stringReference(minAmountFiatText), + minFeeDescription = minFeeNoteValue, + ) + } +} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt index 867fdefd59..0654981fee 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/ui/YieldSupplyActiveContent.kt @@ -91,12 +91,14 @@ internal fun YieldSupplyActiveContent( ) } - Text( - modifier = Modifier.padding(horizontal = 12.dp), - text = stringResourceSafe(R.string.yield_module_fee_policy_sheet_min_amount_note), - style = TangemTheme.typography.caption2, - color = TangemTheme.colors.text.tertiary, - ) + AnimatedVisibility(state.minFeeDescription != null) { + Text( + modifier = Modifier.padding(horizontal = 12.dp), + text = state.minFeeDescription?.resolveReference().orEmpty(), + style = TangemTheme.typography.caption2, + color = TangemTheme.colors.text.tertiary, + ) + } } } @@ -376,6 +378,10 @@ private class YieldSupplyActiveBottomSheetPreviewProvider : PreviewParameterProv ), apy = stringReference("5,14%"), isHighFee = true, + minFeeDescription = stringReference( + "The network fee is currently too high to execute lending." + + "Funds will be supplied once it drops to \$12 or below. ", + ), ), ) } 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 66f9d0f195..0be362037a 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 @@ -10,7 +10,6 @@ import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.url.UrlOpener import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter import com.tangem.core.ui.extensions.* -import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.format import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase @@ -33,7 +32,7 @@ import com.tangem.features.yield.supply.impl.subcomponents.approve.YieldSupplyAp import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsComponent import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsUpdateTrigger import com.tangem.features.yield.supply.impl.subcomponents.notifications.entity.YieldSupplyNotificationData -import com.tangem.utils.StringsSigns.DOT +import com.tangem.core.ui.extensions.TextReference import com.tangem.utils.TangemBlogUrlBuilder import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.transformer.update @@ -220,7 +219,6 @@ internal class YieldSupplyApproveModel @Inject constructor( val feeFiatValue = feeCryptoCurrencyStatus.value.fiatRate?.let { rate -> feeCryptoValue?.multiply(rate) } - val cryptoFee = feeCryptoValue.format { crypto(feeCryptoCurrencyStatus.currency) } val fiatFee = feeFiatValue.format { fiat(appCurrency.code, appCurrency.symbol) } uiState.update { @@ -233,14 +231,11 @@ internal class YieldSupplyApproveModel @Inject constructor( transactionDataList = persistentListOf( approvalTransitionData.copy(fee = transactionFee.normal), ), - feeValue = combinedReference( - stringReference(cryptoFee), - stringReference(" $DOT "), - stringReference(fiatFee), - ), - currentNetworkFeeValue = TextReference.EMPTY, - maxNetworkFeeValue = TextReference.EMPTY, - minAmountFeeValue = TextReference.EMPTY, + feeFiatValue = stringReference(fiatFee), + tokenFeeFiatValue = TextReference.EMPTY, + maxNetworkFeeFiatValue = TextReference.EMPTY, + minTopUpFiatValue = TextReference.EMPTY, + feeNoteValue = TextReference.EMPTY, ), ) } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/YieldSupplyFeePolicyComponent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/YieldSupplyFeePolicyComponent.kt index 2e55b046d0..88976d67ff 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/YieldSupplyFeePolicyComponent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/YieldSupplyFeePolicyComponent.kt @@ -38,7 +38,6 @@ internal class YieldSupplyFeePolicyComponent( YieldSupplyFeePolicyContent( yieldSupplyFeeUM = uiState.yieldSupplyFeeUM, tokenSymbol = params.cryptoCurrency.symbol, - networkName = params.cryptoCurrency.network.name, modifier = modifier, ) } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/ui/YieldSupplyFeePolicyContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/ui/YieldSupplyFeePolicyContent.kt index b9fc7b1d23..90c16fc3df 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/ui/YieldSupplyFeePolicyContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/ui/YieldSupplyFeePolicyContent.kt @@ -6,10 +6,12 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -34,7 +36,6 @@ import kotlinx.collections.immutable.persistentListOf internal fun YieldSupplyFeePolicyContent( yieldSupplyFeeUM: YieldSupplyFeeUM, tokenSymbol: String, - networkName: String, modifier: Modifier = Modifier, ) { Column( @@ -62,68 +63,51 @@ internal fun YieldSupplyFeePolicyContent( modifier = Modifier.padding(horizontal = 16.dp), ) SpacerH24() - FooterContainer( - footer = resourceReference( - id = R.string.yield_module_fee_policy_sheet_min_amount_note, - formatArgs = wrappedList(networkName), - ), - paddingValues = PaddingValues( - top = 8.dp, - start = 12.dp, - end = 12.dp, - ), - ) { - val minAmount = when (yieldSupplyFeeUM) { - is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.minAmountFeeValue - YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) - YieldSupplyFeeUM.Loading -> null - } - YieldSupplyFeeRow( - title = resourceReference(R.string.yield_module_fee_policy_sheet_min_amount_title), - value = minAmount, - ) - } + MinFeeNote(yieldSupplyFeeUM) SpacerH16() + val feeNote = when (yieldSupplyFeeUM) { + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.feeNoteValue + YieldSupplyFeeUM.Error -> null + YieldSupplyFeeUM.Loading -> null + } FooterContainer( - footer = resourceReference( - id = R.string.yield_module_fee_policy_sheet_current_fee_note, - formatArgs = wrappedList(networkName), - ), + footer = feeNote, paddingValues = PaddingValues( top = 8.dp, start = 12.dp, end = 12.dp, ), ) { - val currentFee = when (yieldSupplyFeeUM) { - is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.currentNetworkFeeValue - YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) - YieldSupplyFeeUM.Loading -> null + Column( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(14.dp)) + .background(TangemTheme.colors.background.action) + .padding(horizontal = 16.dp), + ) { + val currentFee = when (yieldSupplyFeeUM) { + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.tokenFeeFiatValue + YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) + YieldSupplyFeeUM.Loading -> null + } + YieldSupplyFeeRow( + title = resourceReference(R.string.yield_module_fee_policy_sheet_current_fee_title), + value = currentFee, + modifier = Modifier.padding(vertical = 12.dp), + ) + val maxFee = when (yieldSupplyFeeUM) { + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.maxNetworkFeeFiatValue + YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) + YieldSupplyFeeUM.Loading -> null + } + YieldSupplyFeeRow( + title = resourceReference(R.string.yield_module_fee_policy_sheet_max_fee_title), + value = maxFee, + modifier = Modifier.padding(vertical = 12.dp), + ) } - YieldSupplyFeeRow( - title = resourceReference(R.string.yield_module_fee_policy_sheet_current_fee_title), - value = currentFee, - ) - } - SpacerH16() - FooterContainer( - footer = resourceReference(R.string.yield_module_fee_policy_sheet_max_fee_note), - paddingValues = PaddingValues( - top = 8.dp, - start = 12.dp, - end = 12.dp, - ), - ) { - val maxFee = when (yieldSupplyFeeUM) { - is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.maxNetworkFeeValue - YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) - YieldSupplyFeeUM.Loading -> null - } - YieldSupplyFeeRow( - title = resourceReference(R.string.yield_module_fee_policy_sheet_max_fee_title), - value = maxFee, - ) } + SpacerH8() Text( text = stringResourceSafe(R.string.yield_module_fee_policy_tangem_service_fee_title), style = TangemTheme.typography.caption2, @@ -139,6 +123,38 @@ internal fun YieldSupplyFeePolicyContent( } } +@Composable +private fun MinFeeNote(yieldSupplyFeeUM: YieldSupplyFeeUM) { + val minFeeNote = when (yieldSupplyFeeUM) { + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.feeNoteValue + YieldSupplyFeeUM.Error -> null + YieldSupplyFeeUM.Loading -> null + } + FooterContainer( + footer = minFeeNote, + paddingValues = PaddingValues( + top = 8.dp, + start = 12.dp, + end = 12.dp, + ), + ) { + val minAmount = when (yieldSupplyFeeUM) { + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.minTopUpFiatValue + YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) + YieldSupplyFeeUM.Loading -> null + } + YieldSupplyFeeRow( + title = resourceReference(R.string.yield_module_fee_policy_sheet_min_amount_title), + value = minAmount, + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(14.dp)) + .background(TangemTheme.colors.background.action) + .padding(horizontal = 16.dp, vertical = 12.dp), + ) + } +} + // region Preview @Composable @Preview(showBackground = true, widthDp = 360) @@ -148,13 +164,21 @@ private fun YieldSupplyFeePolicyContent_Preview() { YieldSupplyFeePolicyContent( yieldSupplyFeeUM = YieldSupplyFeeUM.Content( transactionDataList = persistentListOf(), - feeValue = stringReference("0.0001 ETH • \$1.45"), - maxNetworkFeeValue = stringReference("8.50 USDT • \$8.50"), - currentNetworkFeeValue = stringReference("1.45 USDT • \$1.45"), - minAmountFeeValue = stringReference("50 USDT • \$50"), + feeFiatValue = stringReference("$1.45"), + maxNetworkFeeFiatValue = stringReference("$8.50"), + tokenFeeFiatValue = stringReference("$1.45"), + minTopUpFiatValue = stringReference("$50"), + feeNoteValue = resourceReference( + id = R.string.yield_module_fee_policy_sheet_fee_note, + formatArgs = wrappedList( + stringReference("$1.45"), + stringReference("1.46 USDT"), + stringReference("$8.50"), + stringReference("8.50 USDT"), + ), + ), ), tokenSymbol = "USDT", - networkName = "Ethereum", modifier = Modifier.background(TangemTheme.colors.background.primary), ) } 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 51e5126eb7..184f0fa198 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 @@ -1,17 +1,17 @@ package com.tangem.features.yield.supply.impl.subcomponents.startearning.model.transformers import com.tangem.blockchain.common.TransactionData -import com.tangem.core.ui.extensions.combinedReference +import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.format import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM -import com.tangem.features.yield.supply.impl.common.formatter.YieldSupplyAmountFormatter -import com.tangem.utils.StringsSigns.DOT import com.tangem.utils.transformer.Transformer import kotlinx.collections.immutable.toPersistentList import java.math.BigDecimal @@ -29,30 +29,46 @@ internal class YieldSupplyStartEarningFeeContentTransformer( ) : Transformer { override fun transform(prevState: YieldSupplyActionUM): YieldSupplyActionUM { val cryptoCurrency = cryptoCurrencyStatus.currency - val fiatRate = cryptoCurrencyStatus.value.fiatRate + val tokenFiatRate = cryptoCurrencyStatus.value.fiatRate val feeFiatRate = feeCryptoCurrencyStatus.value.fiatRate - val crypto = feeValue.format { crypto(feeCryptoCurrencyStatus.currency) } - val fiatFeeValue = feeFiatRate?.let(feeValue::multiply) + val feeFiat = feeFiatRate?.let(feeValue::multiply) + val feeFiatValueText = feeFiat.format { fiat(appCurrency.code, appCurrency.symbol) } - val fiat = fiatFeeValue.format { fiat(appCurrency.code, appCurrency.symbol) } - - val tokenCryptoFeeValue = fiatRate?.let { rate -> - fiatFeeValue?.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) + val tokenCryptoFee = tokenFiatRate?.let { rate -> + feeFiat?.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) } + val tokenCryptoFeeValueText = tokenCryptoFee.format { crypto(cryptoCurrency) } + val tokenFiatFee = feeFiat // same fiat amount + val tokenFiatFeeValueText = tokenFiatFee.format { fiat(appCurrency.code, appCurrency.symbol) } - val tokenCryptoFee = tokenCryptoFeeValue.format { crypto(cryptoCurrency) } - - val maxCryptoFee = maxNetworkFee.format { crypto(cryptoCurrency) } - val maxFiatFeeValue = fiatRate?.let { rate -> - maxNetworkFee.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) + val maxFeeCryptoValueText = maxNetworkFee.format { crypto(cryptoCurrency) } + val maxFiatFee = tokenFiatRate?.let { rate -> + maxNetworkFee.multiply(rate) } - val maxFiatFee = maxFiatFeeValue.format { fiat(appCurrency.code, appCurrency.symbol) } + val maxFiatFeeValueText = maxFiatFee.format { fiat(appCurrency.code, appCurrency.symbol) } - val minAmountTextReference = YieldSupplyAmountFormatter( - cryptoCurrency, - appCurrency, - ).invoke(minAmount, cryptoCurrencyStatus.value.fiatRate) + val minAmountCryptoText = minAmount.format { crypto(cryptoCurrency) } + val minAmountFiat = tokenFiatRate?.let(minAmount::multiply) + val minAmountFiatText = minAmountFiat.format { fiat(appCurrency.code, appCurrency.symbol) } + + val feeNoteValue = resourceReference( + id = R.string.yield_module_fee_policy_sheet_fee_note, + formatArgs = wrappedList( + tokenFiatFeeValueText, + tokenCryptoFeeValueText, + maxFiatFeeValueText, + maxFeeCryptoValueText, + ), + ) + + val minFeeNoteValue = resourceReference( + id = R.string.yield_module_fee_policy_sheet_min_amount_note, + formatArgs = wrappedList( + minAmountFiatText, + minAmountCryptoText, + ), + ) return if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading) { prevState.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) @@ -60,22 +76,12 @@ internal class YieldSupplyStartEarningFeeContentTransformer( prevState.copy( yieldSupplyFeeUM = YieldSupplyFeeUM.Content( transactionDataList = updatedTransactionList.toPersistentList(), - feeValue = combinedReference( - stringReference(crypto), - stringReference(" $DOT "), - stringReference(fiat), - ), - currentNetworkFeeValue = combinedReference( - stringReference(tokenCryptoFee), - stringReference(" $DOT "), - stringReference(fiat), - ), - maxNetworkFeeValue = combinedReference( - stringReference(maxCryptoFee), - stringReference(" $DOT "), - stringReference(maxFiatFee), - ), - minAmountFeeValue = minAmountTextReference, + feeFiatValue = stringReference(feeFiatValueText), + tokenFeeFiatValue = stringReference(tokenFiatFeeValueText), + maxNetworkFeeFiatValue = stringReference(maxFiatFeeValueText), + minTopUpFiatValue = stringReference(minAmountFiatText), + feeNoteValue = feeNoteValue, + minFeeNoteValue = minFeeNoteValue, ), ) } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/transformer/YieldSupplyStopEarningFeeContentTransformer.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/transformer/YieldSupplyStopEarningFeeContentTransformer.kt index 4e44bb47e6..0f37c2194d 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/transformer/YieldSupplyStopEarningFeeContentTransformer.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/transformer/YieldSupplyStopEarningFeeContentTransformer.kt @@ -2,16 +2,13 @@ package com.tangem.features.yield.supply.impl.subcomponents.stopearning.model.tr import com.tangem.blockchain.common.TransactionData import com.tangem.core.ui.extensions.TextReference -import com.tangem.core.ui.extensions.combinedReference import com.tangem.core.ui.extensions.stringReference -import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.format import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM -import com.tangem.utils.StringsSigns.DOT import com.tangem.utils.transformer.Transformer import kotlinx.collections.immutable.toPersistentList import java.math.BigDecimal @@ -24,11 +21,10 @@ internal class YieldSupplyStopEarningFeeContentTransformer( private val feeValue: BigDecimal, ) : Transformer { override fun transform(prevState: YieldSupplyActionUM): YieldSupplyActionUM { - val feeFiatValue = feeCryptoCurrencyStatus.value.fiatRate?.let { rate -> + val feeFiatValueRaw = feeCryptoCurrencyStatus.value.fiatRate?.let { rate -> feeValue.multiply(rate) } - val cryptoFee = feeValue.format { crypto(feeCryptoCurrencyStatus.currency) } - val fiatFee = feeFiatValue.format { fiat(appCurrency.code, appCurrency.symbol) } + val fiatFeeText = feeFiatValueRaw.format { fiat(appCurrency.code, appCurrency.symbol) } return if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading) { prevState.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) @@ -37,14 +33,11 @@ internal class YieldSupplyStopEarningFeeContentTransformer( isPrimaryButtonEnabled = true, yieldSupplyFeeUM = YieldSupplyFeeUM.Content( transactionDataList = transactions.toPersistentList(), - feeValue = combinedReference( - stringReference(cryptoFee), - stringReference(" $DOT "), - stringReference(fiatFee), - ), - currentNetworkFeeValue = TextReference.EMPTY, - maxNetworkFeeValue = TextReference.EMPTY, - minAmountFeeValue = TextReference.EMPTY, + feeFiatValue = stringReference(fiatFeeText), + tokenFeeFiatValue = TextReference.EMPTY, + maxNetworkFeeFiatValue = TextReference.EMPTY, + minTopUpFiatValue = TextReference.EMPTY, + feeNoteValue = TextReference.EMPTY, ), ) } From 7d19c86f047a40cdf482e11f1e8a9a71a4726ca8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 23 Oct 2025 10:13:29 +0300 Subject: [PATCH 05/13] Updated on 2026-08-14 --- core/res/src/main/res/values-fr/strings.xml | 75 +++++++++++++++++++ core/res/src/main/res/values-ja/strings.xml | 2 - core/res/src/main/res/values-ru/strings.xml | 9 ++- .../src/main/res/values-uk-rUA/strings.xml | 1 + core/res/src/main/res/values/strings.xml | 16 ++-- .../ui/YieldSupplyFeePolicyContent.kt | 9 ++- 6 files changed, 98 insertions(+), 14 deletions(-) diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index 4685df09fe..8e7c887222 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -1455,5 +1455,80 @@ 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 %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 3% 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 + 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 81,9 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 + Laissez vos fonds travailler pour vous tout en gardant le contrôle. + Les intérêts sont cumulés automatiquement. + Mode de rendement + Traitement de votre dépôt + Faites fructifier vos actifs + 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 68a1c38379..1b9d2b102f 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -1749,7 +1749,6 @@ 手数料が差し引かれ、あなたの資産は再び貸し出されます。 引き続き収益を得るには承認が必要です。 承認を確定する - 資産残高に関するテキスト [プレースホルダー] あなたの%sはAaveに預けられています チャートを読み込めません・・ 受け取った金額%1$s %2$sはAaveに入金されませんでした。 @@ -1776,7 +1775,6 @@ Tangemはまた、得られた利回りに対して3%のサービス手数料を差し引きます。 ネットワーク手数料が下がるか、残高が最低必要額に達すると、資金は自動的にAaveに供給されます。 過去のリターン - ここに説明を入力してください。1〜3行が理想的です。[プレースホルダー] トークンの承認が必要 ネットワーク接続を確認してください ネットワーク手数料についての情報にアクセスできません diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 9f8d33a4a4..e4029c073b 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -1236,6 +1236,7 @@ Отправка средств станет доступной после завершения транзакции(-ий) в сети %s Продажа %s в данный момент не поддерживается ни одним провайдером. Мы работаем над добавлением новых возможностей. Следите за нашими новостями. Стейкинг %s в данный момент не поддерживается ни одним провайдером. Мы работаем над добавлением новых возможностей. Следите за нашими новостями. + Разрешение было отозвано. Ваши средства остаются в Yield сервисе. Чтобы совершать операции, перейдите в Yield сервис и снова выдайте разрешение. Сгенерировать XPUB Скрыть Вы скрываете токен с главного экрана, но в любой момент сможете добавить его обратно через страницу управления токенами. @@ -1570,14 +1571,15 @@ Нет, отправить все Уменьшить на %s XTZ Чтобы не платить повышенную комиссию при следующем пополнении кошелька, уменьшите сумму на %s XTZ - Ваши средства сейчас размещены в протоколе AAVE, но вы можете управлять ими в любое время. + При активном режиме доходности все будущие депозиты на этот адрес будут направляться в Aave. Вы по-прежнему можете свободно управлять своими средствами. Ваш %s внесён в Aave Выдать разрешение - Что-то пошло не так с вашим предыдущим разрешением, поэтому требуется новое. Выберите, как хотите продолжить. + Разрешение для вашего токена было отозвано. Выдайте его снова, чтобы продолжить работу сервиса. Необходимо разрешение Комиссия будет списана, и ваши активы снова начнут приносить доход. Чтобы продолжить зарабатывать, нужно выдать разрешение. Подтвердить разрешение + Ваши средства в данный момент размещены в протоколе Aave, но вы можете воспользоваться ими в любое время. Ваш %s внесён в Aave Невозможно загрузить график Полученная сумма, %1$s %2$s, не была зачислена на Aave. @@ -1600,6 +1602,7 @@ Tangem взимает комиссию за обслуживание в размере 3% от полученного дохода. Ваши средства будут автоматически переведены в Aave, как только комиссия сети снизится или баланс достигнет минимально необходимой суммы. Историческая доходность + Разрешение для вашего токена в Yield сервисе было отозвано. Откройте токен, чтобы выдать разрешение снова. Необходимо разрешение для токена Проверьте ваше интернет соединение Информация о комиссии недоступна @@ -1633,7 +1636,7 @@ APY Пусть ваши деньги работают — зарабатывайте проценты на свой баланс. Проценты начисляются автоматически. - Доходность + Режим доходности Отправка ваших средств Пусть ваш баланс работает на вас! Автоматически 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 ef07e28698..429d57b4f6 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -1433,4 +1433,5 @@ Зменшити на %s XTZ Щоб не платити підвищену комісію при наступному поповненні гаманця, зменште суму на %s XTZ Це найменший депозит, який можна надіслати в Aave. Щоб депозити залишалися прибутковими, ми не обробляємо їх, коли комісія мережі перевищує 4% від суми. + Дозвіл для вашого токена в режимі Yield було відкликано. Відкрийте токен, щоб надати дозвіл знову. diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 5015abed71..6d900d8482 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -1369,7 +1369,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. - Text here + 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. @@ -1812,16 +1812,16 @@ 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 - Your funds are currently supplied to the Aave protocol, but you can manage them at any time. + 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 supplied to Aave. @@ -1832,7 +1832,7 @@ 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 deposited in Aave and earning interest. You hold a%2$s token, which represents your balance and grows over time. When you deposit more funds, they\'ll be supplied to Aave to earn interest, minus a transaction fee. - Earn + Yield mode Total earnings Transfers to Aave Explore Aave @@ -1848,8 +1848,8 @@ Tangem also takes a 3% 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] - Token approvals 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 deposit you make will be supplied to Aave automatically. @@ -1872,7 +1872,7 @@ 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 Disable yield mode diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/ui/YieldSupplyFeePolicyContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/ui/YieldSupplyFeePolicyContent.kt index 90c16fc3df..e6f33bab56 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/ui/YieldSupplyFeePolicyContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/feepolicy/ui/YieldSupplyFeePolicyContent.kt @@ -126,7 +126,7 @@ internal fun YieldSupplyFeePolicyContent( @Composable private fun MinFeeNote(yieldSupplyFeeUM: YieldSupplyFeeUM) { val minFeeNote = when (yieldSupplyFeeUM) { - is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.feeNoteValue + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.minFeeNoteValue YieldSupplyFeeUM.Error -> null YieldSupplyFeeUM.Loading -> null } @@ -177,6 +177,13 @@ private fun YieldSupplyFeePolicyContent_Preview() { stringReference("8.50 USDT"), ), ), + minFeeNoteValue = resourceReference( + id = R.string.yield_module_fee_policy_sheet_min_amount_note, + formatArgs = wrappedList( + stringReference("$2.45"), + stringReference("2.46 USDT"), + ), + ), ), tokenSymbol = "USDT", modifier = Modifier.background(TangemTheme.colors.background.primary), From ece2b12babbcd682ecb8237a3afeab8dc2603f4e Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 23 Oct 2025 09:00:15 +0200 Subject: [PATCH 06/13] Updated on 2026-08-14 --- .../features/staking/impl/presentation/model/StakingModel.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 54636113ff..3c8aa515c4 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,7 +168,7 @@ internal class StakingModel @Inject constructor( } private var isAccountInitialized: Boolean = true - private var cryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull() + private lateinit var cryptoCurrencyStatus: CryptoCurrencyStatus private var stakingActions: List = emptyList() private var feeCryptoCurrencyStatus: CryptoCurrencyStatus? = null private var minimumTransactionAmount: EnterAmountBoundary? = null @@ -1257,6 +1257,7 @@ internal class StakingModel @Inject constructor( } private fun isCaseWithUnitializedTonAccount(): Boolean { + if (!::cryptoCurrencyStatus.isInitialized) return false return value.currentStep == StakingStep.Confirmation && isTon(cryptoCurrencyStatus.currency.network.rawId) && !isAccountInitialized From 2de117d365c0b920cdad23a02aaef10f5d82e79e Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 23 Oct 2025 13:47:54 +0300 Subject: [PATCH 07/13] Updated on 2026-08-14 --- .../organizetokens/OrganizeTokensScreen.kt | 24 +++++++++++++------ gradle/dependencies.toml | 4 ++-- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt index fab2288352..84a19cc5e5 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt @@ -123,6 +123,14 @@ private fun TokenList( end = TangemTheme.dimens.spacing16, ) + // workaround to force recomposition of list items when the list is updated + // because sometimes items disappear after reordering in 1.7.4+ compose-runtime version + // check removing after update to compose-runtime 1.8.0+ + val forceRecompose = remember { mutableIntStateOf(0) } + LaunchedEffect(state.items) { + forceRecompose.intValue++ + } + LazyColumn( modifier = Modifier .align(Alignment.TopCenter) @@ -143,13 +151,15 @@ private fun TokenList( } } - DraggableItem( - index = index, - item = item, - reorderableState = reorderableListState, - onDragStart = onDragStart, - isBalanceHidden = isBalanceHidden, - ) + key(forceRecompose.intValue) { + DraggableItem( + index = index, + item = item, + reorderableState = reorderableListState, + onDragStart = onDragStart, + isBalanceHidden = isBalanceHidden, + ) + } } } diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 35e4b6fd2f..03743696e3 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -34,8 +34,8 @@ androidxWorkManager = "2.9.0" # endregion AndroidX # region Compose -compose-runtime = "1.7.4" -compose-foundation = "1.7.4" +compose-runtime = "1.7.8" +compose-foundation = "1.7.8" compose-material3 = "1.3.1" compose-constraint = "1.0.1" compose-navigation = "2.7.7" From 29db74c3aa261fab2508a831ba3e2fbf9100ff3a Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 23 Oct 2025 13:18:20 +0200 Subject: [PATCH 08/13] Updated on 2026-08-14 --- .../utils/DefaultUserWalletImageFetcher.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/utils/DefaultUserWalletImageFetcher.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/utils/DefaultUserWalletImageFetcher.kt index d27eb2dc8e..f86073d09e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/utils/DefaultUserWalletImageFetcher.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/utils/DefaultUserWalletImageFetcher.kt @@ -45,16 +45,16 @@ class DefaultUserWalletImageFetcher @Inject constructor( .map { allWallets -> allWallets.filter { (walletId, _) -> wallets.any { it.walletId == walletId } } } .distinctUntilChanged() - override fun walletImage(walletId: UserWalletId, size: ArtworkSize): Flow = flow { - val imagesFlow = getUserWalletUseCase.invokeFlow(walletId) - // emit Loading and wait wallet - .onEach { if (it.isLeft()) emit(UserWalletItemUM.ImageState.Loading) } - .filterIsInstance>() - .map { it.value } + override fun walletImage(walletId: UserWalletId, size: ArtworkSize): Flow = + getUserWalletUseCase.invokeFlow(walletId) + .transform { either -> + if (either.isLeft()) { + emit(UserWalletItemUM.ImageState.Loading) + } else if (either is Either.Right) { + emitAll(walletImage(either.value, size)) + } + } .distinctUntilChanged() - .flatMapLatest { wallet -> walletImage(wallet, size) } - emitAll(imagesFlow) - }.distinctUntilChanged() override fun walletImage(cardDTO: CardDTO, size: ArtworkSize): Flow = internalGetCardImage( From cf49333c2299491df05cf7a9f1a99caaea26b44e Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 23 Oct 2025 19:14:48 +0500 Subject: [PATCH 09/13] Updated on 2026-08-14 --- .../swap/model/SwapSelectTokensModel.kt | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/model/SwapSelectTokensModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/model/SwapSelectTokensModel.kt index 5d12338467..9bda5e4153 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/model/SwapSelectTokensModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/model/SwapSelectTokensModel.kt @@ -8,6 +8,7 @@ import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router import com.tangem.core.ui.components.token.state.TokenItemState +import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase @@ -37,6 +38,7 @@ internal class SwapSelectTokensModel @Inject constructor( private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase, private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase, + private val accountsFeatureToggles: AccountsFeatureToggles, ) : Model() { val state: StateFlow = controller.state @@ -77,10 +79,14 @@ internal class SwapSelectTokensModel @Inject constructor( selectedTokenItemState = selectedTokenItemState, onRemoveClick = ::onRemoveFromTokenClick, isAccountsMode = isAccountsMode, - account = getAccountCurrencyStatusUseCase.invokeSync( - userWalletId = params.userWalletId, - currency = status.currency, - ).getOrNull()?.account, + account = if (accountsFeatureToggles.isFeatureEnabled) { + getAccountCurrencyStatusUseCase.invokeSync( + userWalletId = params.userWalletId, + currency = status.currency, + ).getOrNull()?.account + } else { + null + }, ), ) } @@ -104,10 +110,14 @@ internal class SwapSelectTokensModel @Inject constructor( transformer = SelectToTokenTransformer( selectedTokenItemState = selectedTokenItemState, isAccountsMode = isAccountsMode, - account = getAccountCurrencyStatusUseCase.invokeSync( - userWalletId = params.userWalletId, - currency = status.currency, - ).getOrNull()?.account, + account = if (accountsFeatureToggles.isFeatureEnabled) { + getAccountCurrencyStatusUseCase.invokeSync( + userWalletId = params.userWalletId, + currency = status.currency, + ).getOrNull()?.account + } else { + null + }, ), ) From c35da7186d9df3d1bfc7f9465f4921420cb8cd6b Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 23 Oct 2025 17:08:01 +0300 Subject: [PATCH 10/13] Updated on 2026-08-14 --- .../com/tangem/utils/TangemBlogUrlBuilder.kt | 2 +- .../supply/DefaultYieldSupplyRepository.kt | 15 +++ .../supply/models/YieldSupplyEnterStatus.kt | 6 + .../yield/supply/YieldSupplyRepository.kt | 27 +++++ .../supply/impl/common/YieldSupplyTrigger.kt | 39 ------- .../impl/di/YieldSupplyFeatureModule.kt | 17 --- .../impl/main/model/YieldSupplyModel.kt | 110 +++++++----------- .../model/YieldSupplyStartEarningModel.kt | 7 +- .../model/YieldSupplyStopEarningModel.kt | 7 +- 9 files changed, 99 insertions(+), 131 deletions(-) create mode 100644 domain/yield-supply/models/src/main/java/com/tangem/domain/yield/supply/models/YieldSupplyEnterStatus.kt delete mode 100644 features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyTrigger.kt diff --git a/core/utils/src/main/java/com/tangem/utils/TangemBlogUrlBuilder.kt b/core/utils/src/main/java/com/tangem/utils/TangemBlogUrlBuilder.kt index 3bb43d00e2..5d8f4ba63f 100644 --- a/core/utils/src/main/java/com/tangem/utils/TangemBlogUrlBuilder.kt +++ b/core/utils/src/main/java/com/tangem/utils/TangemBlogUrlBuilder.kt @@ -21,7 +21,7 @@ object TangemBlogUrlBuilder { const val RESOURCE_TO_LEARN_ABOUT_APPROVING_IN_SWAP = "https://tangem.com/en/blog/post/give-revoke-permission/" - const val YIELD_SUPPLY_HOW_IT_WORKS_URL = "https://tangem.com/en/blog/post/savings-account" + const val YIELD_SUPPLY_HOW_IT_WORKS_URL = "https://tangem.com/en/blog/post/yield-mode" const val YIELD_SUPPLY_TOS_URL = "https://aave.com/terms-of-service" const val YIELD_SUPPLY_PRIVACY_URL = "https://aave.com/privacy-policy" } \ No newline at end of file diff --git a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt index 8d8613e976..8f5fe85b65 100644 --- a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt +++ b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt @@ -16,11 +16,13 @@ import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.yield.supply.YieldSupplyRepository import com.tangem.domain.yield.supply.models.YieldMarketToken +import com.tangem.domain.yield.supply.models.YieldSupplyEnterStatus import com.tangem.domain.yield.supply.models.YieldSupplyMarketChartData import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext +import java.util.concurrent.ConcurrentHashMap import kotlin.collections.map internal class DefaultYieldSupplyRepository( @@ -30,6 +32,8 @@ internal class DefaultYieldSupplyRepository( private val dispatchers: CoroutineDispatcherProvider, ) : YieldSupplyRepository { + private val statusMap: MutableMap = ConcurrentHashMap() + override suspend fun getCachedMarkets(): List? = withContext(dispatchers.io) { val cache = store.getSyncOrNull().orEmpty() val domain = cache.map(YieldMarketTokenConverter::convert) @@ -97,6 +101,17 @@ internal class DefaultYieldSupplyRepository( ).getOrThrow().isActive } + override suspend fun saveTokenProtocolStatus( + cryptoCurrency: CryptoCurrency, + yieldSupplyEnterStatus: YieldSupplyEnterStatus, + ) { + statusMap[cryptoCurrency.id.value] = yieldSupplyEnterStatus + } + + override fun getTokenProtocolStatus(cryptoCurrencyToken: CryptoCurrency): YieldSupplyEnterStatus? { + return statusMap[cryptoCurrencyToken.id.value] + } + private fun List.enrichNetworkIds(): List { val chainIdMap = Blockchain.entries.associate { it.getChainId() to it.toNetworkId() } return this.map { token -> diff --git a/domain/yield-supply/models/src/main/java/com/tangem/domain/yield/supply/models/YieldSupplyEnterStatus.kt b/domain/yield-supply/models/src/main/java/com/tangem/domain/yield/supply/models/YieldSupplyEnterStatus.kt new file mode 100644 index 0000000000..4ecdb12732 --- /dev/null +++ b/domain/yield-supply/models/src/main/java/com/tangem/domain/yield/supply/models/YieldSupplyEnterStatus.kt @@ -0,0 +1,6 @@ +package com.tangem.domain.yield.supply.models + +enum class YieldSupplyEnterStatus { + Enter, + Exit, +} \ No newline at end of file diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/YieldSupplyRepository.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/YieldSupplyRepository.kt index c721f9e942..a9ce7c69dd 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/YieldSupplyRepository.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/YieldSupplyRepository.kt @@ -3,6 +3,7 @@ package com.tangem.domain.yield.supply import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.yield.supply.models.YieldMarketToken +import com.tangem.domain.yield.supply.models.YieldSupplyEnterStatus import com.tangem.domain.yield.supply.models.YieldSupplyMarketChartData import kotlinx.coroutines.flow.Flow @@ -56,4 +57,30 @@ interface YieldSupplyRepository { */ @Throws suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token): Boolean + + /** + * Save the last user-initiated yield protocol action for the given currency. + * + * The saved value helps the UI render an intermediate "processing" state while waiting + * for the definitive protocol status to be fetched from the network. This information + * is transient and not intended to be persisted across app restarts. + * + * @param cryptoCurrencyToken the currency or token the action relates to + * @param yieldSupplyEnterStatus the last action intent: [YieldSupplyEnterStatus.Enter] or [YieldSupplyEnterStatus.Exit] + */ + suspend fun saveTokenProtocolStatus( + cryptoCurrencyToken: CryptoCurrency, + yieldSupplyEnterStatus: YieldSupplyEnterStatus, + ) + + /** + * Get the last saved user-initiated yield protocol action for the given currency, if any. + * + * Used to determine whether the UI should display an intermediate "processing" state + * until the protocol status retrieved from backend reflects the change. + * + * @param cryptoCurrencyToken the currency or token to query + * @return the last action intent or null if nothing has been recorded + */ + fun getTokenProtocolStatus(cryptoCurrencyToken: CryptoCurrency): YieldSupplyEnterStatus? } \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyTrigger.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyTrigger.kt deleted file mode 100644 index 691095237a..0000000000 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyTrigger.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.tangem.features.yield.supply.impl.common - -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableSharedFlow -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Trigger for entering/exiting protocol from other components - */ -interface YieldSupplyProtocolTrigger { - suspend fun onEnterProtocol() - suspend fun onExitProtocol() -} - -/** - * Listener to observe entering/exiting protocol events - */ -interface YieldSupplyProtocolListener { - val enterProtocolTriggerFlow: Flow - val exitProtocolTriggerFlow: Flow -} - -@Singleton -internal class DefaultYieldSupplyProtocolTrigger @Inject constructor() : - YieldSupplyProtocolTrigger, - YieldSupplyProtocolListener { - - override val enterProtocolTriggerFlow = MutableSharedFlow() - override val exitProtocolTriggerFlow = MutableSharedFlow() - - override suspend fun onEnterProtocol() { - enterProtocolTriggerFlow.emit(Unit) - } - - override suspend fun onExitProtocol() { - exitProtocolTriggerFlow.emit(Unit) - } -} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/di/YieldSupplyFeatureModule.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/di/YieldSupplyFeatureModule.kt index 9226bcfa8e..45b8806bd6 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/di/YieldSupplyFeatureModule.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/di/YieldSupplyFeatureModule.kt @@ -3,10 +3,6 @@ package com.tangem.features.yield.supply.impl.di import com.tangem.core.configtoggle.feature.FeatureTogglesManager import com.tangem.features.yield.supply.impl.DefaultYieldSupplyFeatureToggles import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles -import com.tangem.features.yield.supply.impl.common.DefaultYieldSupplyProtocolTrigger -import com.tangem.features.yield.supply.impl.common.YieldSupplyProtocolListener -import com.tangem.features.yield.supply.impl.common.YieldSupplyProtocolTrigger -import dagger.Binds import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -22,17 +18,4 @@ internal object YieldSupplyFeatureModule { fun provideYieldFeatureToggles(featureTogglesManager: FeatureTogglesManager): YieldSupplyFeatureToggles { return DefaultYieldSupplyFeatureToggles(featureTogglesManager) } -} - -@InstallIn(SingletonComponent::class) -@Module -internal interface YieldSupplyProtocolModuleBinds { - - @Singleton - @Binds - fun bindYieldSupplyProtocolTrigger(impl: DefaultYieldSupplyProtocolTrigger): YieldSupplyProtocolTrigger - - @Singleton - @Binds - fun bindYieldSupplyProtocolListener(impl: DefaultYieldSupplyProtocolTrigger): YieldSupplyProtocolListener } \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt index 70ab6a6a95..a14713f98d 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt @@ -16,12 +16,13 @@ import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.currency.yieldSupplyNotAllAmountSupplied -import com.tangem.domain.models.network.TxInfo import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.yield.supply.YieldSupplyStatus import com.tangem.domain.networks.single.SingleNetworkStatusFetcher import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase +import com.tangem.domain.yield.supply.YieldSupplyRepository +import com.tangem.domain.yield.supply.models.YieldSupplyEnterStatus import com.tangem.domain.yield.supply.usecase.YieldSupplyActivateUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyDeactivateUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase @@ -29,7 +30,6 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyIsAvailableUseCase import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.api.YieldSupplyComponent import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics -import com.tangem.features.yield.supply.impl.common.YieldSupplyProtocolListener import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM import com.tangem.features.yield.supply.impl.main.model.transformers.YieldSupplyTokenStatusSuccessTransformer import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -59,7 +59,7 @@ internal class YieldSupplyModel @Inject constructor( private val yieldSupplyIsAvailableUseCase: YieldSupplyIsAvailableUseCase, private val yieldSupplyActivateUseCase: YieldSupplyActivateUseCase, private val yieldSupplyDeactivateUseCase: YieldSupplyDeactivateUseCase, - private val yieldSupplyProtocolListener: YieldSupplyProtocolListener, + private val yieldSupplyRepository: YieldSupplyRepository, ) : Model(), YieldSupplyClickIntents { private val params = paramsContainer.require() @@ -87,38 +87,6 @@ internal class YieldSupplyModel @Inject constructor( init { checkIfYieldSupplyIsAvailable() - observeProtocolEvents() - } - - private fun observeProtocolEvents() { - yieldSupplyProtocolListener.exitProtocolTriggerFlow.onEach { - uiState.update { - YieldSupplyUM.Processing.Exit - } - coroutineScope.launch(dispatchers.io) { - delay(PROCESSING_UPDATE_DELAY) - singleNetworkStatusFetcher( - params = SingleNetworkStatusFetcher.Params( - userWalletId = userWallet.walletId, - network = cryptoCurrency.network, - ), - ) - } - }.launchIn(modelScope) - yieldSupplyProtocolListener.enterProtocolTriggerFlow.onEach { - uiState.update { - YieldSupplyUM.Processing.Enter - } - coroutineScope.launch(dispatchers.io) { - delay(PROCESSING_UPDATE_DELAY) - singleNetworkStatusFetcher( - params = SingleNetworkStatusFetcher.Params( - userWalletId = userWallet.walletId, - network = cryptoCurrency.network, - ), - ) - } - }.launchIn(modelScope) } private fun checkIfYieldSupplyIsAvailable() { @@ -142,7 +110,6 @@ internal class YieldSupplyModel @Inject constructor( currencyId = cryptoCurrency.id, isSingleWalletWithTokens = false, ).onEach { maybeCryptoCurrency -> - Timber.tag("getSingleCryptoCurrencyStatusUseCase").d("update $maybeCryptoCurrency") maybeCryptoCurrency.fold( ifRight = { cryptoCurrencyStatus -> cryptoCurrencyStatusFlow.update { cryptoCurrencyStatus } @@ -175,7 +142,7 @@ internal class YieldSupplyModel @Inject constructor( ) }.onLeft { Timber.e(it) - uiState.update { YieldSupplyUM.Unavailable } + uiState.update { YieldSupplyUM.Initial } } } } @@ -214,39 +181,46 @@ internal class YieldSupplyModel @Inject constructor( @Suppress("MaximumLineLength") private fun onCryptoCurrencyStatusUpdated(cryptoCurrencyStatus: CryptoCurrencyStatus) { val yieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus - val hasActiveTransaction = cryptoCurrencyStatus.value.hasCurrentNetworkTransactions - val yieldTransaction = cryptoCurrencyStatus.value.pendingTransactions.firstOrNull { - it.type is TxInfo.TransactionType.YieldSupply - }?.type as? TxInfo.TransactionType.YieldSupply + + if ((yieldSupplyStatus == null || yieldSupplyStatus.isActive == false) && + yieldSupplyRepository.getTokenProtocolStatus(cryptoCurrency) == YieldSupplyEnterStatus.Enter) { + uiState.update { + YieldSupplyUM.Processing.Enter + } + fetchCurrencyWithDelay() + return + } + + if (yieldSupplyStatus?.isActive == true && + yieldSupplyRepository.getTokenProtocolStatus(cryptoCurrency) == YieldSupplyEnterStatus.Exit) { + uiState.update { + YieldSupplyUM.Processing.Exit + } + fetchCurrencyWithDelay() + return + } + sendInfoAboutProtocolStatus(cryptoCurrencyStatus) - when { - hasActiveTransaction && yieldTransaction != null -> { - coroutineScope.launch(dispatchers.io) { - delay(PROCESSING_UPDATE_DELAY) - singleNetworkStatusFetcher( - params = SingleNetworkStatusFetcher.Params( - userWalletId = userWallet.walletId, - network = cryptoCurrency.network, - ), - ) - } - uiState.update { - when (yieldTransaction) { - TxInfo.TransactionType.YieldSupply.Enter -> YieldSupplyUM.Processing.Enter - TxInfo.TransactionType.YieldSupply.Exit -> YieldSupplyUM.Processing.Exit - } - } - } - yieldSupplyStatus?.isActive == true -> { - loadActiveState( - cryptoCurrencyStatus = cryptoCurrencyStatus, - yieldSupplyStatus = yieldSupplyStatus, - ) - } - else -> { - loadTokenStatus() - } + if (yieldSupplyStatus?.isActive == true) { + loadActiveState( + cryptoCurrencyStatus = cryptoCurrencyStatus, + yieldSupplyStatus = yieldSupplyStatus, + ) + } else { + loadTokenStatus() + } + } + + private fun fetchCurrencyWithDelay() { + coroutineScope.launch(dispatchers.io) { + delay(PROCESSING_UPDATE_DELAY) + singleNetworkStatusFetcher( + params = SingleNetworkStatusFetcher.Params( + userWalletId = userWallet.walletId, + network = cryptoCurrency.network, + ), + ) } } 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 aaa41615e2..8e409ddc3d 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 @@ -20,6 +20,8 @@ import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.transaction.usecase.SendTransactionUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase +import com.tangem.domain.yield.supply.YieldSupplyRepository +import com.tangem.domain.yield.supply.models.YieldSupplyEnterStatus import com.tangem.domain.yield.supply.usecase.YieldSupplyActivateUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyEstimateEnterFeeUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase @@ -28,7 +30,6 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyStartEarningUseCase import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics import com.tangem.features.yield.supply.impl.common.YieldSupplyAlertFactory -import com.tangem.features.yield.supply.impl.common.YieldSupplyProtocolTrigger import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM import com.tangem.features.yield.supply.impl.common.entity.transformer.YieldSupplyTransactionInProgressTransformer @@ -66,7 +67,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( private val yieldSupplyActivateUseCase: YieldSupplyActivateUseCase, private val yieldSupplyGetTokenStatusUseCase: YieldSupplyGetTokenStatusUseCase, private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase, - private val yieldSupplyProtocolTrigger: YieldSupplyProtocolTrigger, + private val yieldSupplyRepository: YieldSupplyRepository, ) : Model(), YieldSupplyNotificationsComponent.ModelCallback { private val params: YieldSupplyStartEarningComponent.Params = paramsContainer.require() @@ -252,7 +253,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( ) }, ifRight = { - yieldSupplyProtocolTrigger.onEnterProtocol() + yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Enter) analytics.send(YieldSupplyAnalytics.FundsEarned) yieldSupplyActivateUseCase(cryptoCurrency) modelScope.launch { 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 268ab35f31..4ab5059e24 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,12 +16,13 @@ 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.YieldSupplyRepository +import com.tangem.domain.yield.supply.models.YieldSupplyEnterStatus import com.tangem.domain.yield.supply.usecase.YieldSupplyDeactivateUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyStopEarningUseCase import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics import com.tangem.features.yield.supply.impl.common.YieldSupplyAlertFactory -import com.tangem.features.yield.supply.impl.common.YieldSupplyProtocolTrigger import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM import com.tangem.features.yield.supply.impl.common.entity.transformer.YieldSupplyTransactionInProgressTransformer @@ -55,7 +56,7 @@ internal class YieldSupplyStopEarningModel @Inject constructor( private val yieldSupplyNotificationsUpdateTrigger: YieldSupplyNotificationsUpdateTrigger, private val yieldSupplyAlertFactory: YieldSupplyAlertFactory, private val yieldSupplyDeactivateUseCase: YieldSupplyDeactivateUseCase, - private val yieldSupplyProtocolTrigger: YieldSupplyProtocolTrigger, + private val yieldSupplyRepository: YieldSupplyRepository, ) : Model(), YieldSupplyNotificationsComponent.ModelCallback { private val params: YieldSupplyStopEarningComponent.Params = paramsContainer.require() @@ -158,7 +159,7 @@ internal class YieldSupplyStopEarningModel @Inject constructor( ) }, ifRight = { - yieldSupplyProtocolTrigger.onExitProtocol() + yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Exit) analytics.send( YieldSupplyAnalytics.FundsWithdrawn( token = cryptoCurrency.symbol, From 32c644f4583381f9a9427b0ad52542b2e4448507 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 23 Oct 2025 17:21:59 +0300 Subject: [PATCH 11/13] Updated on 2026-08-14 --- .../impl/main/model/YieldSupplyModel.kt | 45 +++++++++---------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt index a14713f98d..9d5b7885d9 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt @@ -181,34 +181,29 @@ internal class YieldSupplyModel @Inject constructor( @Suppress("MaximumLineLength") private fun onCryptoCurrencyStatusUpdated(cryptoCurrencyStatus: CryptoCurrencyStatus) { val yieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus + val tokenProtocolStatus = yieldSupplyRepository.getTokenProtocolStatus(cryptoCurrency) + val isActive = yieldSupplyStatus?.isActive == true - if ((yieldSupplyStatus == null || yieldSupplyStatus.isActive == false) && - yieldSupplyRepository.getTokenProtocolStatus(cryptoCurrency) == YieldSupplyEnterStatus.Enter) { - uiState.update { - YieldSupplyUM.Processing.Enter + when { + !isActive && tokenProtocolStatus == YieldSupplyEnterStatus.Enter -> { + uiState.update { YieldSupplyUM.Processing.Enter } + fetchCurrencyWithDelay() } - fetchCurrencyWithDelay() - return - } - - if (yieldSupplyStatus?.isActive == true && - yieldSupplyRepository.getTokenProtocolStatus(cryptoCurrency) == YieldSupplyEnterStatus.Exit) { - uiState.update { - YieldSupplyUM.Processing.Exit + isActive && tokenProtocolStatus == YieldSupplyEnterStatus.Exit -> { + uiState.update { YieldSupplyUM.Processing.Exit } + fetchCurrencyWithDelay() + } + else -> { + sendInfoAboutProtocolStatus(cryptoCurrencyStatus) + if (isActive) { + loadActiveState( + cryptoCurrencyStatus = cryptoCurrencyStatus, + yieldSupplyStatus = requireNotNull(yieldSupplyStatus), + ) + } else { + loadTokenStatus() + } } - fetchCurrencyWithDelay() - return - } - - sendInfoAboutProtocolStatus(cryptoCurrencyStatus) - - if (yieldSupplyStatus?.isActive == true) { - loadActiveState( - cryptoCurrencyStatus = cryptoCurrencyStatus, - yieldSupplyStatus = yieldSupplyStatus, - ) - } else { - loadTokenStatus() } } From a9f59dfc9a7329727318c84063005556ecf4207a Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 23 Oct 2025 14:36:35 +0000 Subject: [PATCH 12/13] 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 1cd201c597..f7e514619e 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-1285" +tangemBlockchainSdk = "develop-1287" #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 0a5f0775f2115f5df76f810568f09f340c8dce36 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 24 Oct 2025 00:05:54 +0300 Subject: [PATCH 13/13] Updated on 2026-08-14 --- core/res/src/main/res/values-de/strings.xml | 61 ++++++++++++++-- core/res/src/main/res/values-es/strings.xml | 78 +++++++++++++++++++++ core/res/src/main/res/values-ru/strings.xml | 5 +- core/res/src/main/res/values/strings.xml | 7 +- tangem-android-tools | 2 +- 5 files changed, 142 insertions(+), 11 deletions(-) diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index ee000bb82f..d03a24ea12 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -1675,31 +1675,82 @@ 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 - Dies ist die niedrigste Einzahlung, die an Aave gesendet werden kann. Um Einzahlungen rentabel zu halten, verarbeiten wir sie nicht, wenn die Netzwerkgebühren 4 % des Betrags übersteigen. + 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 3% 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? + Aave ist ein dezentrales Protokoll, das einen Gesamtwert von über 81,9 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 %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 + Effektiver Jahreszins Lass Dein Geld arbeiten – verdiene Zinsen auf Dein Guthaben. - Verdienst auf Dein Guthaben + Zinsen fallen automatisch an + Ertragsmodus + Bearbeitung Deiner Einzahlung Lass dein Guthaben arbeiten + 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 98241d95b8..4a8daa7d9e 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -1476,4 +1476,82 @@ 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 3% 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 81.9 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 + Deje que sus fondos hagan el trabajo mientras usted mantiene el control. + Los intereses se devengan automáticamente + Modo de rendimiento + Procesando su depósito + Haga que sus activos trabajen para usted + 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-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index e4029c073b..143ab7e150 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -395,6 +395,7 @@ Больше провайдеров на подходе.\nСледите за обновлениями! Провайдер Лучший курс + Лучший выбор Доступно до %s Доступно с %s Недоступно для этой пары @@ -1642,7 +1643,7 @@ Автоматически Внесите немного %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 6d900d8482..f93fca2b20 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -249,6 +249,7 @@ Enable Enabled Error + Estimated fee Swap Explore Explore transaction history @@ -484,7 +485,7 @@ Provider Best rate FCA Warning List - Great rate + Best choice Provider in FCA warning list Available up to %s Available from %s @@ -1888,7 +1889,7 @@ 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/tangem-android-tools b/tangem-android-tools index b64f8659fc..4e92adf6ed 160000 --- a/tangem-android-tools +++ b/tangem-android-tools @@ -1 +1 @@ -Subproject commit b64f8659fce65e7749d50923b32bfad13e6b8cac +Subproject commit 4e92adf6ed23e0e79f60ce769d921256cc257241