From abd604f9f1a32576d8ff0b8c4bb90a280fd74339 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 5 Nov 2025 16:23:19 +0300 Subject: [PATCH 1/9] Updated on 2026-08-14 --- .../java/com/tangem/domain/feedback/FeedbackDataBuilder.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt index e5f65f4c77..4722b56cb9 100644 --- a/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt +++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt @@ -101,6 +101,10 @@ internal class FeedbackDataBuilder { fun addBlockchainError(info: BlockchainInfo, error: BlockchainErrorInfo) { builder.appendKeyValue("Blockchain", info.blockchain) + builder.appendAddresses( + key = "Explorer link${info.explorerLinks.isMultiple(suffix = "s")}", + addresses = info.explorerLinks, + ) builder.appendKeyValue("Derivation path", info.derivationPath) builder.appendKeyValue("Host", info.host) builder.appendKeyValue("Token", error.tokenSymbol) From 802b914e784f75cc72668b04d7b7c710c45fdfc0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 5 Nov 2025 19:38:38 +0500 Subject: [PATCH 2/9] Updated on 2026-08-14 --- .../tap/di/domain/YieldSupplyDomainModule.kt | 4 ++-- .../yield/supply/models/YieldSupplyMaxFee.kt | 9 +++++++++ ...kt => YieldSupplyGetTokenMaxFeeUseCase.kt} | 20 ++++++++++++------- .../api/analytics/YieldSupplyAnalytics.kt | 9 ++++++++- .../active/model/YieldSupplyActiveModel.kt | 8 ++++---- .../YieldSupplyActiveFeeContentTransformer.kt | 14 ++++++++----- .../model/YieldSupplyStartEarningModel.kt | 19 +++++++----------- ...SupplyStartEarningFeeContentTransformer.kt | 11 +++++----- 8 files changed, 57 insertions(+), 37 deletions(-) create mode 100644 domain/yield-supply/models/src/main/java/com/tangem/domain/yield/supply/models/YieldSupplyMaxFee.kt rename domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/{YieldSupplyGetMaxFeeUseCase.kt => YieldSupplyGetTokenMaxFeeUseCase.kt} (81%) diff --git a/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt index ea0ad78e44..4e7acbe2eb 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt @@ -169,8 +169,8 @@ internal object YieldSupplyDomainModule { yieldSupplyRepository: YieldSupplyRepository, quotesRepository: QuotesRepository, currenciesRepository: CurrenciesRepository, - ): YieldSupplyGetMaxFeeUseCase { - return YieldSupplyGetMaxFeeUseCase( + ): YieldSupplyGetTokenMaxFeeUseCase { + return YieldSupplyGetTokenMaxFeeUseCase( yieldSupplyRepository = yieldSupplyRepository, quotesRepository = quotesRepository, currenciesRepository = currenciesRepository, diff --git a/domain/yield-supply/models/src/main/java/com/tangem/domain/yield/supply/models/YieldSupplyMaxFee.kt b/domain/yield-supply/models/src/main/java/com/tangem/domain/yield/supply/models/YieldSupplyMaxFee.kt new file mode 100644 index 0000000000..160d52d47b --- /dev/null +++ b/domain/yield-supply/models/src/main/java/com/tangem/domain/yield/supply/models/YieldSupplyMaxFee.kt @@ -0,0 +1,9 @@ +package com.tangem.domain.yield.supply.models + +import java.math.BigDecimal + +data class YieldSupplyMaxFee( + val nativeMaxFee: BigDecimal, + val tokenMaxFee: BigDecimal, + val fiatMaxFee: 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/YieldSupplyGetTokenMaxFeeUseCase.kt similarity index 81% rename from domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetMaxFeeUseCase.kt rename to domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetTokenMaxFeeUseCase.kt index 60a316b9f7..ca6f2af240 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/YieldSupplyGetTokenMaxFeeUseCase.kt @@ -10,21 +10,22 @@ import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.quotes.QuotesRepository import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.yield.supply.YieldSupplyRepository +import com.tangem.domain.yield.supply.models.YieldSupplyMaxFee import java.math.BigDecimal import java.math.RoundingMode /** * Calculates the max allowed network fee for a Yield Supply transaction. * - * Result is a Pair where: - * - first: fee in native coin units (maxFeeNative) - * - second: the same fee converted to token units using the fiat-rate ratio - * (nativeFiatRate / tokenFiatRate). + * Returns [Either] of [YieldSupplyMaxFee] with: + * - nativeMaxFee: fee in native coin units + * - tokenMaxFee: fee converted to token units using the native/token rate ratio + * - tokenFiatMaxFee: fee value in fiat * * Uses YieldMarketToken.maxFeeNative and the same conversion logic as * [YieldSupplyGetCurrentFeeUseCase]. */ -class YieldSupplyGetMaxFeeUseCase( +class YieldSupplyGetTokenMaxFeeUseCase( private val yieldSupplyRepository: YieldSupplyRepository, private val quotesRepository: QuotesRepository, private val currenciesRepository: CurrenciesRepository, @@ -33,7 +34,7 @@ class YieldSupplyGetMaxFeeUseCase( suspend operator fun invoke( userWallet: UserWallet, cryptoCurrencyStatus: CryptoCurrencyStatus, - ): Either> = catch { + ): Either = catch { val token = cryptoCurrencyStatus.currency as? CryptoCurrency.Token ?: error("CryptoCurrency must be token for max fee calculation") @@ -60,6 +61,7 @@ class YieldSupplyGetMaxFeeUseCase( .firstOrNull { it.yieldSupplyKey == token.yieldSupplyKey() } val marketToken = cachedMarketToken ?: yieldSupplyRepository.getTokenStatus(token) val maxFeeNative = marketToken.maxFeeNative + val maxFeeToken = maxFeeNative.multiply(nativeFiatRate) val rateRatio = nativeFiatRate.divide( fiatRate, @@ -69,6 +71,10 @@ class YieldSupplyGetMaxFeeUseCase( val tokenValue = rateRatio.multiply(maxFeeNative) - maxFeeNative to tokenValue.stripTrailingZeros() + YieldSupplyMaxFee( + nativeMaxFee = maxFeeNative, + tokenMaxFee = maxFeeToken, + fiatMaxFee = tokenValue.stripTrailingZeros(), + ) } } \ No newline at end of file diff --git a/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt b/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt index 32c5975417..942e3a3d8a 100644 --- a/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt +++ b/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/analytics/YieldSupplyAnalytics.kt @@ -99,8 +99,15 @@ sealed class YieldSupplyAnalytics( ), ) - data object FundsEarned : YieldSupplyAnalytics( + data class FundsEarned( + val token: String, + val blockchain: String, + ) : YieldSupplyAnalytics( event = "Funds Earned", + params = mapOf( + TOKEN_PARAM to token, + BLOCKCHAIN to blockchain, + ), ) data class FundsWithdrawn( 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 bfb21a8ec9..e5cae54445 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 @@ -21,7 +21,7 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyGetProtocolBalanceUseCa import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyMinAmountUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyGetCurrentFeeUseCase -import com.tangem.domain.yield.supply.usecase.YieldSupplyGetMaxFeeUseCase +import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenMaxFeeUseCase import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyActiveComponent @@ -50,7 +50,7 @@ internal class YieldSupplyActiveModel @Inject constructor( private val yieldSupplyGetTokenStatusUseCase: YieldSupplyGetTokenStatusUseCase, private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase, private val yieldSupplyGetCurrentFeeUseCase: YieldSupplyGetCurrentFeeUseCase, - private val yieldSupplyGetMaxFeeUseCase: YieldSupplyGetMaxFeeUseCase, + private val yieldSupplyGetTokenMaxFeeUseCase: YieldSupplyGetTokenMaxFeeUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, ) : Model() { @@ -237,7 +237,7 @@ internal class YieldSupplyActiveModel @Inject constructor( cryptoCurrencyStatus = cryptoStatus, ).getOrNull() - val maxFee = yieldSupplyGetMaxFeeUseCase( + val maxFee = yieldSupplyGetTokenMaxFeeUseCase( userWallet = params.userWallet, cryptoCurrencyStatus = cryptoStatus, ).getOrNull() @@ -248,7 +248,7 @@ internal class YieldSupplyActiveModel @Inject constructor( cryptoCurrencyStatus = cryptoStatus, appCurrency = appCurrency, feeValue = currentFee, - maxNetworkFee = maxFee.second, + maxNetworkFee = maxFee, analyticsHandler = analyticsHandler, ), ) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveFeeContentTransformer.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveFeeContentTransformer.kt index cc7f66e762..dbabb4a9f5 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveFeeContentTransformer.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/transformers/YieldSupplyActiveFeeContentTransformer.kt @@ -10,6 +10,7 @@ import com.tangem.core.ui.format.bigdecimal.format import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.yield.supply.models.YieldSupplyMaxFee import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM @@ -23,7 +24,7 @@ internal class YieldSupplyActiveFeeContentTransformer( private val cryptoCurrencyStatus: CryptoCurrencyStatus, private val appCurrency: AppCurrency, private val feeValue: BigDecimal, - private val maxNetworkFee: BigDecimal, + private val maxNetworkFee: YieldSupplyMaxFee, private val analyticsHandler: AnalyticsEventHandler, ) : Transformer { @@ -35,9 +36,12 @@ internal class YieldSupplyActiveFeeContentTransformer( 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 maxFeeCryptoValueText = maxNetworkFee.tokenMaxFee.format { crypto(cryptoCurrency) } + val maxFiatFeeValueText = maxNetworkFee.fiatMaxFee.format { fiat( + appCurrency.code, + appCurrency + .symbol, + ) } val feeNoteValue: TextReference = resourceReference( id = R.string.yield_module_fee_policy_sheet_fee_note, @@ -49,7 +53,7 @@ internal class YieldSupplyActiveFeeContentTransformer( ), ) - val isHighFee = feeValue > maxNetworkFee + val isHighFee = feeValue > maxNetworkFee.tokenMaxFee if (isHighFee) { analyticsHandler.send( 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 c9dc6d5b65..59b294d623 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 @@ -62,7 +62,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( private val yieldSupplyAlertFactory: YieldSupplyAlertFactory, private val yieldSupplyActivateUseCase: YieldSupplyActivateUseCase, private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase, - private val yieldSupplyGetMaxFeeUseCase: YieldSupplyGetMaxFeeUseCase, + private val yieldSupplyGetTokenMaxFeeUseCase: YieldSupplyGetTokenMaxFeeUseCase, private val yieldSupplyRepository: YieldSupplyRepository, ) : Model(), YieldSupplyNotificationsComponent.ModelCallback { @@ -130,10 +130,6 @@ internal class YieldSupplyStartEarningModel @Inject constructor( } } - private suspend fun getMaxFeePair(): Pair? { - return yieldSupplyGetMaxFeeUseCase(userWallet, cryptoCurrencyStatus).getOrNull() - } - private suspend fun onLoadFee() { if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading || uiState.value.isTransactionSending) return @@ -141,15 +137,12 @@ internal class YieldSupplyStartEarningModel @Inject constructor( it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) } - val maxFeePair = getMaxFeePair() ?: return - - val maxFee = maxFeePair.first - val maxFeeFiat = maxFeePair.second + val maxFee = yieldSupplyGetTokenMaxFeeUseCase(userWallet, cryptoCurrencyStatus).getOrNull() ?: return val transactionListData = yieldSupplyStartEarningUseCase( userWalletId = userWallet.walletId, cryptoCurrencyStatus = cryptoCurrencyStatus, - maxNetworkFee = maxFee, + maxNetworkFee = maxFee.nativeMaxFee, ).getOrNull() if (transactionListData == null) { @@ -194,7 +187,6 @@ internal class YieldSupplyStartEarningModel @Inject constructor( updatedTransactionList = updatedTransactionList, feeValue = feeSum, maxNetworkFee = maxFee, - maxNetworkFeeFiat = maxFeeFiat, minAmount = minAmount, ), ) @@ -255,7 +247,10 @@ internal class YieldSupplyStartEarningModel @Inject constructor( token = cryptoCurrency.symbol, feeType = AnalyticsParam.FeeType.Normal, ) - analytics.send(YieldSupplyAnalytics.FundsEarned) + analytics.send(YieldSupplyAnalytics.FundsEarned( + blockchain = cryptoCurrency.network.name, + token = cryptoCurrency.symbol, + )) yieldSupplyFeeUM.transactionDataList.forEach { analytics.send( Basic.TransactionSent( 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 189ffa8a23..19696a8a93 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 @@ -9,6 +9,7 @@ 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.domain.yield.supply.models.YieldSupplyMaxFee 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 @@ -24,8 +25,7 @@ internal class YieldSupplyStartEarningFeeContentTransformer( private val appCurrency: AppCurrency, private val updatedTransactionList: List, private val feeValue: BigDecimal, - private val maxNetworkFee: BigDecimal, - private val maxNetworkFeeFiat: BigDecimal, + private val maxNetworkFee: YieldSupplyMaxFee, private val minAmount: BigDecimal, ) : Transformer { override fun transform(prevState: YieldSupplyActionUM): YieldSupplyActionUM { @@ -40,11 +40,10 @@ internal class YieldSupplyStartEarningFeeContentTransformer( 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 tokenFiatFeeValueText = feeFiat.format { fiat(appCurrency.code, appCurrency.symbol) } - val maxFeeCryptoValueText = maxNetworkFee.format { crypto(cryptoCurrency) } - val maxFiatFeeValueText = maxNetworkFeeFiat.format { fiat(appCurrency.code, appCurrency.symbol) } + val maxFeeCryptoValueText = maxNetworkFee.tokenMaxFee.format { crypto(cryptoCurrency) } + val maxFiatFeeValueText = maxNetworkFee.fiatMaxFee.format { fiat(appCurrency.code, appCurrency.symbol) } val minAmountCryptoText = minAmount.format { crypto(cryptoCurrency) } val minAmountFiat = tokenFiatRate?.let(minAmount::multiply) From 506c1bb737fdca24a25e5b2b81405351c471c544 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 5 Nov 2025 20:11:39 +0500 Subject: [PATCH 3/9] Updated on 2026-08-14 --- .../com/tangem/tap/di/domain/YieldSupplyDomainModule.kt | 4 ++-- ...TokenMaxFeeUseCase.kt => YieldSupplyGetMaxFeeUseCase.kt} | 2 +- .../subcomponents/active/model/YieldSupplyActiveModel.kt | 6 +++--- .../startearning/model/YieldSupplyStartEarningModel.kt | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) rename domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/{YieldSupplyGetTokenMaxFeeUseCase.kt => YieldSupplyGetMaxFeeUseCase.kt} (98%) diff --git a/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt index 4e7acbe2eb..ea0ad78e44 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/YieldSupplyDomainModule.kt @@ -169,8 +169,8 @@ internal object YieldSupplyDomainModule { yieldSupplyRepository: YieldSupplyRepository, quotesRepository: QuotesRepository, currenciesRepository: CurrenciesRepository, - ): YieldSupplyGetTokenMaxFeeUseCase { - return YieldSupplyGetTokenMaxFeeUseCase( + ): YieldSupplyGetMaxFeeUseCase { + return YieldSupplyGetMaxFeeUseCase( yieldSupplyRepository = yieldSupplyRepository, quotesRepository = quotesRepository, currenciesRepository = currenciesRepository, diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetTokenMaxFeeUseCase.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetMaxFeeUseCase.kt similarity index 98% rename from domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetTokenMaxFeeUseCase.kt rename to domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetMaxFeeUseCase.kt index ca6f2af240..b7f7417185 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetTokenMaxFeeUseCase.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetMaxFeeUseCase.kt @@ -25,7 +25,7 @@ import java.math.RoundingMode * Uses YieldMarketToken.maxFeeNative and the same conversion logic as * [YieldSupplyGetCurrentFeeUseCase]. */ -class YieldSupplyGetTokenMaxFeeUseCase( +class YieldSupplyGetMaxFeeUseCase( private val yieldSupplyRepository: YieldSupplyRepository, private val quotesRepository: QuotesRepository, private val currenciesRepository: CurrenciesRepository, 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 e5cae54445..070ec52cb7 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/active/model/YieldSupplyActiveModel.kt @@ -21,7 +21,7 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyGetProtocolBalanceUseCa import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyMinAmountUseCase import com.tangem.domain.yield.supply.usecase.YieldSupplyGetCurrentFeeUseCase -import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenMaxFeeUseCase +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.subcomponents.active.YieldSupplyActiveComponent @@ -50,7 +50,7 @@ internal class YieldSupplyActiveModel @Inject constructor( private val yieldSupplyGetTokenStatusUseCase: YieldSupplyGetTokenStatusUseCase, private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase, private val yieldSupplyGetCurrentFeeUseCase: YieldSupplyGetCurrentFeeUseCase, - private val yieldSupplyGetTokenMaxFeeUseCase: YieldSupplyGetTokenMaxFeeUseCase, + private val yieldSupplyGetMaxFeeUseCase: YieldSupplyGetMaxFeeUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, ) : Model() { @@ -237,7 +237,7 @@ internal class YieldSupplyActiveModel @Inject constructor( cryptoCurrencyStatus = cryptoStatus, ).getOrNull() - val maxFee = yieldSupplyGetTokenMaxFeeUseCase( + val maxFee = yieldSupplyGetMaxFeeUseCase( userWallet = params.userWallet, cryptoCurrencyStatus = cryptoStatus, ).getOrNull() 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 59b294d623..357bd430ee 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 @@ -62,7 +62,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( private val yieldSupplyAlertFactory: YieldSupplyAlertFactory, private val yieldSupplyActivateUseCase: YieldSupplyActivateUseCase, private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase, - private val yieldSupplyGetTokenMaxFeeUseCase: YieldSupplyGetTokenMaxFeeUseCase, + private val yieldSupplyGetMaxFeeUseCase: YieldSupplyGetMaxFeeUseCase, private val yieldSupplyRepository: YieldSupplyRepository, ) : Model(), YieldSupplyNotificationsComponent.ModelCallback { @@ -137,7 +137,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) } - val maxFee = yieldSupplyGetTokenMaxFeeUseCase(userWallet, cryptoCurrencyStatus).getOrNull() ?: return + val maxFee = yieldSupplyGetMaxFeeUseCase(userWallet, cryptoCurrencyStatus).getOrNull() ?: return val transactionListData = yieldSupplyStartEarningUseCase( userWalletId = userWallet.walletId, From 540ee066e2e4cfa9393708eb4daa7b84c993810b Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 5 Nov 2025 20:52:32 +0500 Subject: [PATCH 4/9] Updated on 2026-08-14 --- .../yield/supply/impl/common/entity/YieldSupplyFeeUM.kt | 2 ++ .../supply/impl/common/ui/YieldSupplyActionContent.kt | 1 + .../approve/model/YieldSupplyApproveModel.kt | 1 + .../feepolicy/ui/YieldSupplyFeePolicyContent.kt | 3 ++- .../startearning/model/YieldSupplyStartEarningModel.kt | 3 +++ .../YieldSupplyStartEarningFeeContentTransformer.kt | 9 +++++++-- .../YieldSupplyStopEarningFeeContentTransformer.kt | 1 + 7 files changed, 17 insertions(+), 3 deletions(-) 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 ccc975f7ff..ee74e2b820 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,6 +13,8 @@ internal sealed class YieldSupplyFeeUM { data class Content( val transactionDataList: ImmutableList, val feeFiatValue: TextReference, + // TODO move to FeePolicyUM + val estimatedFiatValue: TextReference, val tokenFeeFiatValue: TextReference, val maxNetworkFeeFiatValue: TextReference, val minTopUpFiatValue: TextReference, 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 abc8b25b63..177149a2f3 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 @@ -149,6 +149,7 @@ private class YieldSupplyActionContentPreviewProvider : PreviewParameterProvider maxNetworkFeeFiatValue = stringReference("$8.50"), minTopUpFiatValue = stringReference("$50"), feeNoteValue = TextReference.EMPTY, + estimatedFiatValue = TextReference.EMPTY, ), isPrimaryButtonEnabled = false, isTransactionSending = false, 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 3e43bf02a5..bb92b7315b 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 @@ -255,6 +255,7 @@ internal class YieldSupplyApproveModel @Inject constructor( maxNetworkFeeFiatValue = TextReference.EMPTY, minTopUpFiatValue = TextReference.EMPTY, feeNoteValue = TextReference.EMPTY, + estimatedFiatValue = TextReference.EMPTY, ), ) } 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 e6f33bab56..ec32b8e52b 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 @@ -86,7 +86,7 @@ internal fun YieldSupplyFeePolicyContent( .padding(horizontal = 16.dp), ) { val currentFee = when (yieldSupplyFeeUM) { - is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.tokenFeeFiatValue + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.estimatedFiatValue YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) YieldSupplyFeeUM.Loading -> null } @@ -184,6 +184,7 @@ private fun YieldSupplyFeePolicyContent_Preview() { stringReference("2.46 USDT"), ), ), + estimatedFiatValue = stringReference("$8.50"), ), tokenSymbol = "USDT", 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/YieldSupplyStartEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt index 357bd430ee..c205b40b6b 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 @@ -63,6 +63,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( private val yieldSupplyActivateUseCase: YieldSupplyActivateUseCase, private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase, private val yieldSupplyGetMaxFeeUseCase: YieldSupplyGetMaxFeeUseCase, + private val yieldSupplyGetCurrentFeeUseCase: YieldSupplyGetCurrentFeeUseCase, private val yieldSupplyRepository: YieldSupplyRepository, ) : Model(), YieldSupplyNotificationsComponent.ModelCallback { @@ -138,6 +139,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( } val maxFee = yieldSupplyGetMaxFeeUseCase(userWallet, cryptoCurrencyStatus).getOrNull() ?: return + val estimatedFee = yieldSupplyGetCurrentFeeUseCase(userWallet, cryptoCurrencyStatus).getOrNull() ?: return val transactionListData = yieldSupplyStartEarningUseCase( userWalletId = userWallet.walletId, @@ -187,6 +189,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( updatedTransactionList = updatedTransactionList, feeValue = feeSum, maxNetworkFee = maxFee, + estimatedFeeValue = estimatedFee, minAmount = minAmount, ), ) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt index 19696a8a93..8c189f61d8 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt @@ -25,6 +25,7 @@ internal class YieldSupplyStartEarningFeeContentTransformer( private val appCurrency: AppCurrency, private val updatedTransactionList: List, private val feeValue: BigDecimal, + private val estimatedFeeValue: BigDecimal, private val maxNetworkFee: YieldSupplyMaxFee, private val minAmount: BigDecimal, ) : Transformer { @@ -36,11 +37,14 @@ internal class YieldSupplyStartEarningFeeContentTransformer( val feeFiat = feeFiatRate?.let(feeValue::multiply) val feeFiatValueText = feeFiat.format { fiat(appCurrency.code, appCurrency.symbol) } + val estimatedFeeFiat = feeFiatRate?.let(estimatedFeeValue::multiply) + val estimatedFeeFiatValueText = estimatedFeeFiat.format { fiat(appCurrency.code, appCurrency.symbol) } + val tokenCryptoFee = tokenFiatRate?.let { rate -> - feeFiat?.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) + estimatedFeeFiat?.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) } val tokenCryptoFeeValueText = tokenCryptoFee.format { crypto(cryptoCurrency) } - val tokenFiatFeeValueText = feeFiat.format { fiat(appCurrency.code, appCurrency.symbol) } + val tokenFiatFeeValueText = estimatedFeeFiat.format { fiat(appCurrency.code, appCurrency.symbol) } val maxFeeCryptoValueText = maxNetworkFee.tokenMaxFee.format { crypto(cryptoCurrency) } val maxFiatFeeValueText = maxNetworkFee.fiatMaxFee.format { fiat(appCurrency.code, appCurrency.symbol) } @@ -79,6 +83,7 @@ internal class YieldSupplyStartEarningFeeContentTransformer( minTopUpFiatValue = stringReference(minAmountFiatText), feeNoteValue = feeNoteValue, minFeeNoteValue = minFeeNoteValue, + estimatedFiatValue = stringReference(estimatedFeeFiatValueText), ), ) } 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 0f37c2194d..6c1881f305 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 @@ -38,6 +38,7 @@ internal class YieldSupplyStopEarningFeeContentTransformer( maxNetworkFeeFiatValue = TextReference.EMPTY, minTopUpFiatValue = TextReference.EMPTY, feeNoteValue = TextReference.EMPTY, + estimatedFiatValue = TextReference.EMPTY, ), ) } From 7e5a678d84ae5a738d0785b80617dc808a104f8e Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 6 Nov 2025 22:10:57 +0500 Subject: [PATCH 5/9] Updated on 2026-08-14 --- .../supply/DefaultYieldSupplyRepository.kt | 10 ++- .../yield/supply/YieldSupplyRepository.kt | 19 ++++-- .../impl/main/model/YieldSupplyModel.kt | 5 +- .../model/YieldSupplyStartEarningModel.kt | 64 +++++++++++-------- .../model/YieldSupplyStopEarningModel.kt | 60 +++++++++-------- 5 files changed, 95 insertions(+), 63 deletions(-) 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 082d68a3d2..84d2441b9e 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 @@ -103,14 +103,18 @@ internal class DefaultYieldSupplyRepository( } override suspend fun saveTokenProtocolStatus( + userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency, yieldSupplyEnterStatus: YieldSupplyEnterStatus, ) { - statusMap[cryptoCurrency.id.value] = yieldSupplyEnterStatus + statusMap["${userWalletId}_${cryptoCurrency.id.value}"] = yieldSupplyEnterStatus } - override fun getTokenProtocolStatus(cryptoCurrency: CryptoCurrency): YieldSupplyEnterStatus? { - return statusMap[cryptoCurrency.id.value] + override fun getTokenProtocolStatus( + userWalletId: UserWalletId, + cryptoCurrency: CryptoCurrency, + ): YieldSupplyEnterStatus? { + return statusMap["${userWalletId}_${cryptoCurrency.id.value}"] } private fun List.enrichNetworkIds(): List { 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 deb3c44851..2a62e896fd 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 @@ -59,25 +59,32 @@ interface YieldSupplyRepository { suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean /** - * Save the last user-initiated yield protocol action for the given currency. + * Save the last user‑initiated yield protocol action for the given wallet and 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. + * is transient (in‑memory only) and is not persisted across app restarts. * + * @param userWalletId the wallet the action was performed with * @param cryptoCurrency the currency or token the action relates to * @param yieldSupplyEnterStatus the last action intent: [YieldSupplyEnterStatus.Enter] or [YieldSupplyEnterStatus.Exit] */ - suspend fun saveTokenProtocolStatus(cryptoCurrency: CryptoCurrency, yieldSupplyEnterStatus: YieldSupplyEnterStatus) + suspend fun saveTokenProtocolStatus( + userWalletId: UserWalletId, + cryptoCurrency: CryptoCurrency, + yieldSupplyEnterStatus: YieldSupplyEnterStatus, + ) /** - * Get the last saved user-initiated yield protocol action for the given currency, if any. + * Get the last saved user‑initiated yield protocol action for the given wallet and 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. + * until the protocol status retrieved from backend reflects the change. The value is + * transient (in‑memory only) and is not persisted across app restarts. * + * @param userWalletId the wallet to query * @param cryptoCurrency the currency or token to query * @return the last action intent or null if nothing has been recorded */ - fun getTokenProtocolStatus(cryptoCurrency: CryptoCurrency): YieldSupplyEnterStatus? + fun getTokenProtocolStatus(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): YieldSupplyEnterStatus? } \ 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 bf4ac35878..f60bda9cea 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 @@ -185,7 +185,10 @@ internal class YieldSupplyModel @Inject constructor( @Suppress("MaximumLineLength") private fun onCryptoCurrencyStatusUpdated(cryptoCurrencyStatus: CryptoCurrencyStatus) { val yieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus - val tokenProtocolStatus = yieldSupplyRepository.getTokenProtocolStatus(cryptoCurrency) + val tokenProtocolStatus = yieldSupplyRepository.getTokenProtocolStatus( + userWallet.walletId, + cryptoCurrency, + ) val isActive = yieldSupplyStatus?.isActive == true val isCryptoCurrencyStatusFromCache = cryptoCurrencyStatus.value.sources.networkSource != StatusSource.ACTUAL val processing = uiState.value is YieldSupplyUM.Processing 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 c205b40b6b..bb8781d903 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 @@ -244,38 +244,48 @@ internal class YieldSupplyStartEarningModel @Inject constructor( ) }, ifRight = { - yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Enter) - val event = AnalyticsParam.TxSentFrom.Earning( - blockchain = cryptoCurrency.network.name, - token = cryptoCurrency.symbol, - feeType = AnalyticsParam.FeeType.Normal, - ) - analytics.send(YieldSupplyAnalytics.FundsEarned( - blockchain = cryptoCurrency.network.name, - token = cryptoCurrency.symbol, - )) - yieldSupplyFeeUM.transactionDataList.forEach { - analytics.send( - Basic.TransactionSent( - sentFrom = event, - memoType = Basic.TransactionSent.MemoType.Null, - ), - ) - } - - val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value - if (address != null) { - yieldSupplyActivateUseCase(cryptoCurrency, address) - } - - modelScope.launch { - params.callback.onTransactionSent() - } + onStartEarningTransactionSuccess(yieldSupplyFeeUM) }, ) } } + private suspend fun onStartEarningTransactionSuccess(yieldSupplyFeeUM: YieldSupplyFeeUM.Content) { + yieldSupplyRepository.saveTokenProtocolStatus( + userWallet.walletId, + cryptoCurrency, + YieldSupplyEnterStatus.Enter, + ) + val event = AnalyticsParam.TxSentFrom.Earning( + blockchain = cryptoCurrency.network.name, + token = cryptoCurrency.symbol, + feeType = AnalyticsParam.FeeType.Normal, + ) + analytics.send( + YieldSupplyAnalytics.FundsEarned( + blockchain = cryptoCurrency.network.name, + token = cryptoCurrency.symbol, + ), + ) + yieldSupplyFeeUM.transactionDataList.forEach { + analytics.send( + Basic.TransactionSent( + sentFrom = event, + memoType = Basic.TransactionSent.MemoType.Null, + ), + ) + } + + val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value + if (address != null) { + yieldSupplyActivateUseCase(cryptoCurrency, address) + } + + modelScope.launch { + params.callback.onTransactionSent() + } + } + private fun subscribeOnCurrencyStatusUpdates() { modelScope.launch { getUserWalletUseCase(params.userWalletId).fold( 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 658dd165bb..c9dc0ec5fd 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 @@ -165,37 +165,45 @@ internal class YieldSupplyStopEarningModel @Inject constructor( ) }, ifRight = { - yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Exit) - analytics.send( - YieldSupplyAnalytics.FundsWithdrawn( - token = cryptoCurrency.symbol, - blockchain = cryptoCurrency.network.name, - ), - ) - val event = AnalyticsParam.TxSentFrom.Earning( - blockchain = cryptoCurrency.network.name, - token = cryptoCurrency.symbol, - feeType = AnalyticsParam.FeeType.Normal, - ) - analytics.send( - Basic.TransactionSent( - sentFrom = event, - memoType = Basic.TransactionSent.MemoType.Null, - ), - ) - val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value - if (address != null) { - yieldSupplyDeactivateUseCase(cryptoCurrency, address) - } - - modelScope.launch { - params.callback.onTransactionSent() - } + onStopEarningTransactionSuccess() }, ) } } + private suspend fun onStopEarningTransactionSuccess() { + yieldSupplyRepository.saveTokenProtocolStatus( + userWallet.walletId, + cryptoCurrency, + YieldSupplyEnterStatus.Exit, + ) + analytics.send( + YieldSupplyAnalytics.FundsWithdrawn( + token = cryptoCurrency.symbol, + blockchain = cryptoCurrency.network.name, + ), + ) + val event = AnalyticsParam.TxSentFrom.Earning( + blockchain = cryptoCurrency.network.name, + token = cryptoCurrency.symbol, + feeType = AnalyticsParam.FeeType.Normal, + ) + analytics.send( + Basic.TransactionSent( + sentFrom = event, + memoType = Basic.TransactionSent.MemoType.Null, + ), + ) + val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value + if (address != null) { + yieldSupplyDeactivateUseCase(cryptoCurrency, address) + } + + modelScope.launch { + params.callback.onTransactionSent() + } + } + private fun subscribeOnCurrencyStatusUpdates() { modelScope.launch { feeCryptoCurrencyStatusFlow.update { From d442154b826afebe75f352c20b4d933abd7a20ba Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 6 Nov 2025 18:00:16 +0500 Subject: [PATCH 6/9] Updated on 2026-08-14 --- .../tangem/tap/routing/utils/ChildFactory.kt | 1 + .../com/tangem/common/routing/AppRoute.kt | 2 + .../ui/tokens/TokenItemStateConverter.kt | 4 ++ .../models/event/MainScreenAnalyticsEvent.kt | 18 ++++++++ .../core/ui/components/token/TokenItem.kt | 1 + .../components/token/internal/TokenTitle.kt | 13 ++++-- .../components/token/state/TokenItemState.kt | 9 ++++ .../tokens/model/details/NavigationAction.kt | 9 ++++ .../tokendetails/TokenDetailsComponent.kt | 2 + .../DefaultTokenDetailsComponent.kt | 3 ++ .../tokendetails/model/TokenDetailsModel.kt | 8 ++++ .../intents/WalletContentClickIntents.kt | 42 +++++++++++++++++++ .../router/DefaultWalletRouter.kt | 8 +++- .../presentation/router/InnerWalletRouter.kt | 7 +++- .../converter/TokenListStateConverter.kt | 5 +++ .../yield/supply/api/YieldSupplyComponent.kt | 1 + .../impl/main/model/YieldSupplyModel.kt | 10 +++++ 17 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/details/NavigationAction.kt diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index e75766a69a..2059299bb3 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -284,6 +284,7 @@ internal class ChildFactory @Inject constructor( params = TokenDetailsComponent.Params( userWalletId = route.userWalletId, currency = route.currency, + navigationAction = route.navigationAction, ), componentFactory = tokenDetailsComponentFactory, ) diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index ea0474e6e9..d9f6179153 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -19,6 +19,7 @@ import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.nft.models.NFTAsset import com.tangem.domain.onramp.model.OnrampSource import com.tangem.domain.pay.TangemPayDetailsConfig +import com.tangem.domain.tokens.model.details.NavigationAction import kotlinx.serialization.Serializable @SuppressLint("UnsafeOptInUsageError") @@ -54,6 +55,7 @@ sealed class AppRoute(val path: String) : Route { data class CurrencyDetails( val userWalletId: UserWalletId, val currency: CryptoCurrency, + val navigationAction: NavigationAction? = null, ) : AppRoute(path = "/currency_details/${userWalletId.stringValue}/${currency.id.value}") @Serializable 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 9ba606d735..2376f947d8 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 @@ -62,6 +62,7 @@ class TokenItemStateConverter( }, private val onItemClick: ((TokenItemState, CryptoCurrencyStatus) -> Unit)? = null, private val onItemLongClick: ((TokenItemState, CryptoCurrencyStatus) -> Unit)? = null, + private val onApyLabelClick: ((TokenItemState, CryptoCurrencyStatus) -> Unit)? = null, ) : Converter { override fun convert(value: CryptoCurrencyStatus): TokenItemState { @@ -102,6 +103,9 @@ class TokenItemStateConverter( onItemLongClick = onItemLongClick?.let { onItemLongClick -> { onItemLongClick(it, this) } }, + onApyLabelClick = onApyLabelClick?.let { onApyLabelClick -> + { onApyLabelClick(it, this) } + }, ) } diff --git a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/MainScreenAnalyticsEvent.kt b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/MainScreenAnalyticsEvent.kt index 879b87a6f9..c8864d3617 100644 --- a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/MainScreenAnalyticsEvent.kt +++ b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/MainScreenAnalyticsEvent.kt @@ -2,7 +2,10 @@ package com.tangem.core.analytics.models.event import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.analytics.models.AnalyticsParam.Key.ACTION +import com.tangem.core.analytics.models.AnalyticsParam.Key.BLOCKCHAIN import com.tangem.core.analytics.models.AnalyticsParam.Key.ERROR_CODE +import com.tangem.core.analytics.models.AnalyticsParam.Key.STATE import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM /** @@ -108,6 +111,21 @@ sealed class MainScreenAnalyticsEvent( event = "Hot Token Error", params = mapOf(ERROR_CODE to errorCode), ) + + data class ApyClicked( + val token: String, + val blockchain: String, + val action: String, + val state: String, + ) : MainScreenAnalyticsEvent( + event = "APY Clicked", + params = mapOf( + TOKEN_PARAM to token, + BLOCKCHAIN to blockchain, + ACTION to action, + STATE to state, + ), + ) // endregion companion object { diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/token/TokenItem.kt b/core/ui/src/main/java/com/tangem/core/ui/components/token/TokenItem.kt index 68212fff41..c3401e3a9e 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/token/TokenItem.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/token/TokenItem.kt @@ -110,6 +110,7 @@ fun TokenItem( TokenTitle( state = state.titleState, + onApyClick = { state.onApyLabelClick?.invoke(state) }, modifier = Modifier .layoutId(layoutId = LayoutId.TITLE) .padding(end = TangemTheme.dimens.spacing8) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenTitle.kt b/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenTitle.kt index f762f3b848..113bd58668 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenTitle.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenTitle.kt @@ -3,6 +3,7 @@ package com.tangem.core.ui.components.token.internal import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -20,10 +21,10 @@ import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.components.token.state.TokenItemState.TitleState as TokenTitleState @Composable -internal fun TokenTitle(state: TokenTitleState?, modifier: Modifier = Modifier) { +internal fun TokenTitle(state: TokenTitleState?, onApyClick: () -> Unit, modifier: Modifier = Modifier) { when (state) { is TokenTitleState.Content -> { - ContentTitle(state = state, modifier = modifier) + ContentTitle(state = state, modifier = modifier, onApyClick = onApyClick) } is TokenTitleState.Loading -> { RectangleShimmer(modifier = modifier.placeholderSize(), radius = TangemTheme.dimens.radius4) @@ -36,7 +37,7 @@ internal fun TokenTitle(state: TokenTitleState?, modifier: Modifier = Modifier) } @Composable -private fun ContentTitle(state: TokenTitleState.Content, modifier: Modifier = Modifier) { +private fun ContentTitle(state: TokenTitleState.Content, onApyClick: () -> Unit, modifier: Modifier = Modifier) { Row( modifier = modifier, horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing6), @@ -60,7 +61,11 @@ private fun ContentTitle(state: TokenTitleState.Content, modifier: Modifier = Mo YieldSupplyApyLabel( apy = state.earnApy, isActive = state.earnApyIsActive, - modifier = Modifier.align(alignment = Alignment.CenterVertically), + modifier = Modifier + .align(alignment = Alignment.CenterVertically) + .clickable { + onApyClick() + }, ) } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt b/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt index 88fc97f796..f9ae59685b 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt @@ -40,6 +40,9 @@ sealed class TokenItemState { /** Callback which will be called when an item is long clicked */ abstract val onItemLongClick: ((TokenItemState) -> Unit)? + /** Callback which will be called when an apy label is clicked */ + abstract val onApyLabelClick: ((TokenItemState) -> Unit)? + /** * Loading token state * @@ -58,6 +61,7 @@ sealed class TokenItemState { override val subtitle2State: Subtitle2State = Subtitle2State.Loading override val onItemClick: ((TokenItemState) -> Unit)? = null override val onItemLongClick: ((TokenItemState) -> Unit)? = null + override val onApyLabelClick: ((TokenItemState) -> Unit)? = null } /** @@ -73,6 +77,7 @@ sealed class TokenItemState { override val subtitle2State: Subtitle2State = Subtitle2State.Locked override val onItemClick: ((TokenItemState) -> Unit)? = null override val onItemLongClick: ((TokenItemState) -> Unit)? = null + override val onApyLabelClick: ((TokenItemState) -> Unit)? = null } /** @@ -96,6 +101,7 @@ sealed class TokenItemState { override val subtitle2State: Subtitle2State?, override val onItemClick: ((TokenItemState) -> Unit)?, override val onItemLongClick: ((TokenItemState) -> Unit)?, + override val onApyLabelClick: ((TokenItemState) -> Unit)? = null, ) : TokenItemState() /** @@ -116,6 +122,7 @@ sealed class TokenItemState { override val fiatAmountState: FiatAmountState? = null override val onItemClick: ((TokenItemState) -> Unit)? = null override val onItemLongClick: ((TokenItemState) -> Unit)? = null + override val onApyLabelClick: ((TokenItemState) -> Unit)? = null } /** @@ -133,6 +140,7 @@ sealed class TokenItemState { override val iconState: CurrencyIconState, override val titleState: TitleState, override val subtitleState: SubtitleState? = null, + override val onApyLabelClick: ((TokenItemState) -> Unit)? = null, override val onItemClick: ((TokenItemState) -> Unit)?, override val onItemLongClick: ((TokenItemState) -> Unit)?, ) : TokenItemState() { @@ -159,6 +167,7 @@ sealed class TokenItemState { override val fiatAmountState: FiatAmountState? = null override val subtitle2State: Subtitle2State? = null override val onItemClick: ((TokenItemState) -> Unit)? = null + override val onApyLabelClick: ((TokenItemState) -> Unit)? = null } @Immutable diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/details/NavigationAction.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/details/NavigationAction.kt new file mode 100644 index 0000000000..e3343ec90b --- /dev/null +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/details/NavigationAction.kt @@ -0,0 +1,9 @@ +package com.tangem.domain.tokens.model.details + +import kotlinx.serialization.Serializable + +@Serializable +sealed class NavigationAction { + data object Staking : NavigationAction() + data class YieldSupply(val isActive: Boolean) : NavigationAction() +} \ No newline at end of file diff --git a/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt b/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt index 5dd736294e..8192a29732 100644 --- a/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt +++ b/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt @@ -4,12 +4,14 @@ import com.tangem.core.decompose.factory.ComponentFactory import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.domain.tokens.model.details.NavigationAction interface TokenDetailsComponent : ComposableContentComponent { data class Params( val userWalletId: UserWalletId, val currency: CryptoCurrency, + val navigationAction: NavigationAction? = null, ) interface Factory : ComponentFactory diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt index 5de293633a..4f4dbe32e0 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt @@ -16,6 +16,7 @@ import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.ui.components.NavigationBar3ButtonsScrim import com.tangem.core.ui.decompose.ComposableBottomSheetComponent import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.tokens.model.details.NavigationAction import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsModel import com.tangem.feature.tokendetails.presentation.tokendetails.route.TokenDetailsBottomSheetConfig import com.tangem.feature.tokendetails.presentation.tokendetails.ui.TokenDetailsScreen @@ -76,6 +77,8 @@ internal class DefaultTokenDetailsComponent @AssistedInject constructor( params = YieldSupplyComponent.Params( userWalletId = params.userWalletId, cryptoCurrency = params.currency, + handleNavigation = (params.navigationAction as? NavigationAction.YieldSupply) + ?.isActive, ), ) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt index f89bc25347..de7ae04637 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt @@ -62,6 +62,7 @@ import com.tangem.domain.tokens.model.TokenActionsState import com.tangem.domain.tokens.model.analytics.* import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.toReasonAnalyticsText import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.DetailsScreenOpened.TokenBalance +import com.tangem.domain.tokens.model.details.NavigationAction import com.tangem.domain.tokens.model.details.TokenAction import com.tangem.domain.transaction.error.AssociateAssetError import com.tangem.domain.transaction.error.IncompleteTransactionError @@ -218,6 +219,7 @@ internal class TokenDetailsModel @Inject constructor( updateContent() handleBalanceHiding() checkForActionUpdates() + handleNavigationParam() } fun onResume() { @@ -1221,6 +1223,12 @@ internal class TokenDetailsModel @Inject constructor( } } + private fun handleNavigationParam() { + if (params.navigationAction is NavigationAction.Staking) { + openStaking() + } + } + private companion object { const val EXPRESS_STATUS_UPDATE_DELAY = 10_000L } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt index 39e5b37251..198caf6fd9 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt @@ -3,9 +3,12 @@ package com.tangem.feature.wallet.child.wallet.model.intents import arrow.core.getOrElse import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent import com.tangem.core.decompose.di.ModelScoped import com.tangem.domain.models.account.Account +import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.staking.YieldBalance import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.isLocked @@ -14,6 +17,7 @@ import com.tangem.domain.settings.ShouldShowMarketsTooltipUseCase import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.model.TokenActionsState +import com.tangem.domain.tokens.model.details.NavigationAction import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.feature.wallet.presentation.account.AccountDependencies @@ -45,6 +49,8 @@ internal interface WalletContentClickIntents { fun onTokenItemLongClick(userWalletId: UserWalletId, cryptoCurrencyStatus: CryptoCurrencyStatus) + fun onApyLabelClick(userWalletId: UserWalletId, currencyStatus: CryptoCurrencyStatus) + fun onAccountExpandClick(account: Account) fun onAccountCollapseClick(account: Account) @@ -154,6 +160,42 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( } } + override fun onApyLabelClick(userWalletId: UserWalletId, currencyStatus: CryptoCurrencyStatus) { + val navigationAction = if (currencyStatus.currency is CryptoCurrency.Token) { + NavigationAction.YieldSupply(currencyStatus.value.yieldSupplyStatus?.isActive == true) + } else { + NavigationAction.Staking + } + val event = when (navigationAction) { + is NavigationAction.YieldSupply -> { + MainScreenAnalyticsEvent.ApyClicked( + token = currencyStatus.currency.symbol, + blockchain = currencyStatus.currency.network.name, + action = "Earning", + state = if (currencyStatus.value.yieldSupplyStatus?.isActive == true) { + "Enabled" + } else { + "Disabled" + }, + ) + } + is NavigationAction.Staking -> { + MainScreenAnalyticsEvent.ApyClicked( + token = currencyStatus.currency.symbol, + blockchain = currencyStatus.currency.network.name, + action = "Staking", + state = if (currencyStatus.value.yieldBalance is YieldBalance.Data) { + "Enabled" + } else { + "Disabled" + }, + ) + } + } + analyticsEventHandler.send(event) + router.openTokenDetails(userWalletId, currencyStatus, navigationAction) + } + override fun onAccountExpandClick(account: Account) { val userWalletId = stateHolder.getSelectedWalletId() accountDependencies.expandedAccountsHolder.expandAccount(userWalletId, account.accountId) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt index 8213172d17..ceae6da7cd 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt @@ -15,6 +15,7 @@ import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.pay.TangemPayDetailsConfig import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.redux.StateDialog +import com.tangem.domain.tokens.model.details.NavigationAction import com.tangem.domain.tokens.model.details.TokenAction import com.tangem.feature.wallet.navigation.WalletRoute import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig @@ -66,13 +67,18 @@ internal class DefaultWalletRouter @Inject constructor( urlOpener.openUrl(url) } - override fun openTokenDetails(userWalletId: UserWalletId, currencyStatus: CryptoCurrencyStatus) { + override fun openTokenDetails( + userWalletId: UserWalletId, + currencyStatus: CryptoCurrencyStatus, + navigationAction: NavigationAction?, + ) { val networkAddress = currencyStatus.value.networkAddress if (networkAddress != null && networkAddress.defaultAddress.value.isNotEmpty()) { router.push( AppRoute.CurrencyDetails( userWalletId = userWalletId, currency = currencyStatus.currency, + navigationAction = navigationAction, ), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt index d869ca8b84..ea0edf104c 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt @@ -9,6 +9,7 @@ import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.pay.TangemPayDetailsConfig +import com.tangem.domain.tokens.model.details.NavigationAction import com.tangem.domain.tokens.model.details.TokenAction import com.tangem.feature.wallet.navigation.WalletRoute import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig @@ -42,7 +43,11 @@ internal interface InnerWalletRouter { fun openUrl(url: String) /** Open token details screen */ - fun openTokenDetails(userWalletId: UserWalletId, currencyStatus: CryptoCurrencyStatus) + fun openTokenDetails( + userWalletId: UserWalletId, + currencyStatus: CryptoCurrencyStatus, + navigationAction: NavigationAction? = null, + ) /** Open stories screen */ fun openStoriesScreen() diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt index 34ade399d3..c11ff8c4b1 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt @@ -49,12 +49,17 @@ internal class TokenListStateConverter( clickIntents.onTokenItemLongClick(selectedWallet.walletId, currencyStatus) } + private val onApyLabelClick: (currencyStatus: CryptoCurrencyStatus) -> Unit = { currencyStatus -> + clickIntents.onApyLabelClick(selectedWallet.walletId, currencyStatus) + } + private fun tokenStatusConverter(accountId: AccountId? = null) = TokenItemStateConverter( appCurrency = appCurrency, yieldModuleApyMap = yieldModuleApyMap, stakingApyMap = stakingApyMap, onItemClick = { _, status -> onTokenClick(accountId, status) }, onItemLongClick = { _, status -> onTokenLongClick(accountId, status) }, + onApyLabelClick = { _, status -> onApyLabelClick(status) }, ) override fun convert(value: WalletTokensListState): WalletTokensListState { diff --git a/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/YieldSupplyComponent.kt b/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/YieldSupplyComponent.kt index af868285e3..c2f5cf26f0 100644 --- a/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/YieldSupplyComponent.kt +++ b/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/YieldSupplyComponent.kt @@ -10,6 +10,7 @@ interface YieldSupplyComponent : ComposableContentComponent { data class Params( val userWalletId: UserWalletId, val cryptoCurrency: CryptoCurrency, + val handleNavigation: Boolean? = null, ) interface Factory : ComponentFactory 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 f60bda9cea..36d3f0f8b6 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 @@ -91,6 +91,16 @@ internal class YieldSupplyModel @Inject constructor( init { checkIfYieldSupplyIsAvailable() + if (params.handleNavigation != null) { + if (params.handleNavigation == true) { + modelScope.launch { + delay(timeMillis = 1000) + bottomSheetNavigation.activate(Unit) + } + } else { + onStartEarningClick() + } + } } private fun checkIfYieldSupplyIsAvailable() { From 3c80a5325410adaa5450d7a3aac6fcf972ddfc2c Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 6 Nov 2025 18:50:08 +0500 Subject: [PATCH 7/9] Updated on 2026-08-14 --- .../tangem/common/ui/tokens/TokenItemStateConverter.kt | 10 +++++++--- .../com/tangem/core/ui/components/token/TokenItem.kt | 1 - .../core/ui/components/token/internal/TokenTitle.kt | 8 ++++---- .../core/ui/components/token/state/TokenItemState.kt | 1 + .../transformers/converter/TokenListStateConverter.kt | 2 +- .../yield/supply/impl/main/model/YieldSupplyModel.kt | 4 ++-- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt b/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt index 2376f947d8..2d3c6e516a 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 @@ -48,8 +48,11 @@ class TokenItemStateConverter( private val iconStateProvider: (CryptoCurrencyStatus) -> CurrencyIconState = { CryptoCurrencyToIconStateConverter().convert(it) }, + private val onApyLabelClick: ((CryptoCurrencyStatus) -> Unit)? = null, private val titleStateProvider: (CryptoCurrencyStatus) -> TokenItemState.TitleState = { - createTitleState(it, yieldModuleApyMap, stakingApyMap) + createTitleState(it, yieldModuleApyMap, stakingApyMap, { + onApyLabelClick?.invoke(it) + }) }, private val subtitleStateProvider: (CryptoCurrencyStatus) -> TokenItemState.SubtitleState? = { createSubtitleState(it, appCurrency) @@ -62,7 +65,6 @@ class TokenItemStateConverter( }, private val onItemClick: ((TokenItemState, CryptoCurrencyStatus) -> Unit)? = null, private val onItemLongClick: ((TokenItemState, CryptoCurrencyStatus) -> Unit)? = null, - private val onApyLabelClick: ((TokenItemState, CryptoCurrencyStatus) -> Unit)? = null, ) : Converter { override fun convert(value: CryptoCurrencyStatus): TokenItemState { @@ -104,7 +106,7 @@ class TokenItemStateConverter( { onItemLongClick(it, this) } }, onApyLabelClick = onApyLabelClick?.let { onApyLabelClick -> - { onApyLabelClick(it, this) } + { onApyLabelClick(this) } }, ) } @@ -164,6 +166,7 @@ class TokenItemStateConverter( currencyStatus: CryptoCurrencyStatus, yieldModuleApyMap: Map, stakingApyMap: Map>, + onApyLabelClick: () -> Unit, ): TokenItemState.TitleState { return when (val value = currencyStatus.value) { is CryptoCurrencyStatus.Loading, @@ -188,6 +191,7 @@ class TokenItemStateConverter( hasPending = value.hasCurrentNetworkTransactions, earnApy = earnApyText, earnApyIsActive = isActive, + onApyLabelClick = onApyLabelClick, ) } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/token/TokenItem.kt b/core/ui/src/main/java/com/tangem/core/ui/components/token/TokenItem.kt index c3401e3a9e..68212fff41 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/token/TokenItem.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/token/TokenItem.kt @@ -110,7 +110,6 @@ fun TokenItem( TokenTitle( state = state.titleState, - onApyClick = { state.onApyLabelClick?.invoke(state) }, modifier = Modifier .layoutId(layoutId = LayoutId.TITLE) .padding(end = TangemTheme.dimens.spacing8) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenTitle.kt b/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenTitle.kt index 113bd58668..ed61f2011d 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenTitle.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenTitle.kt @@ -21,10 +21,10 @@ import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.components.token.state.TokenItemState.TitleState as TokenTitleState @Composable -internal fun TokenTitle(state: TokenTitleState?, onApyClick: () -> Unit, modifier: Modifier = Modifier) { +internal fun TokenTitle(state: TokenTitleState?, modifier: Modifier = Modifier) { when (state) { is TokenTitleState.Content -> { - ContentTitle(state = state, modifier = modifier, onApyClick = onApyClick) + ContentTitle(state = state, modifier = modifier) } is TokenTitleState.Loading -> { RectangleShimmer(modifier = modifier.placeholderSize(), radius = TangemTheme.dimens.radius4) @@ -37,7 +37,7 @@ internal fun TokenTitle(state: TokenTitleState?, onApyClick: () -> Unit, modifie } @Composable -private fun ContentTitle(state: TokenTitleState.Content, onApyClick: () -> Unit, modifier: Modifier = Modifier) { +private fun ContentTitle(state: TokenTitleState.Content, modifier: Modifier = Modifier) { Row( modifier = modifier, horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing6), @@ -64,7 +64,7 @@ private fun ContentTitle(state: TokenTitleState.Content, onApyClick: () -> Unit, modifier = Modifier .align(alignment = Alignment.CenterVertically) .clickable { - onApyClick() + state.onApyLabelClick?.invoke() }, ) } diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt b/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt index f9ae59685b..1f8a4ea2b6 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt @@ -179,6 +179,7 @@ sealed class TokenItemState { val isAvailable: Boolean = true, val earnApy: TextReference? = null, val earnApyIsActive: Boolean = false, + val onApyLabelClick: (() -> Unit)? = null, ) : TitleState() data object Loading : TitleState() diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt index c11ff8c4b1..7e7fcc6351 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt @@ -59,7 +59,7 @@ internal class TokenListStateConverter( stakingApyMap = stakingApyMap, onItemClick = { _, status -> onTokenClick(accountId, status) }, onItemLongClick = { _, status -> onTokenLongClick(accountId, status) }, - onApyLabelClick = { _, status -> onApyLabelClick(status) }, + onApyLabelClick = { status -> onApyLabelClick(status) }, ) override fun convert(value: WalletTokensListState): WalletTokensListState { 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 36d3f0f8b6..b7e828f6fd 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 @@ -91,8 +91,8 @@ internal class YieldSupplyModel @Inject constructor( init { checkIfYieldSupplyIsAvailable() - if (params.handleNavigation != null) { - if (params.handleNavigation == true) { + params.handleNavigation?.let { handle -> + if (handle) { modelScope.launch { delay(timeMillis = 1000) bottomSheetNavigation.activate(Unit) From 5514e3a195731c4f7a2e6d8e908bb26e0337fd94 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 6 Nov 2025 22:12:26 +0500 Subject: [PATCH 8/9] Updated on 2026-08-14 --- .../api/tangemTech/YieldSupplyApi.kt | 2 ++ .../supply/DefaultYieldSupplyRepository.kt | 28 +++++++++++-------- .../yield/supply/YieldSupplyRepository.kt | 6 +++- .../usecase/YieldSupplyActivateUseCase.kt | 18 ++++++++---- .../impl/main/model/YieldSupplyModel.kt | 6 +++- .../model/YieldSupplyStartEarningModel.kt | 6 +++- ...SupplyStartEarningFeeContentTransformer.kt | 4 +-- 7 files changed, 48 insertions(+), 22 deletions(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/YieldSupplyApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/YieldSupplyApi.kt index 6ed56e4ce7..baaa9e2bd7 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/YieldSupplyApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/YieldSupplyApi.kt @@ -8,6 +8,7 @@ import com.tangem.datasource.api.tangemTech.models.YieldSupplyMarketTokenDto import com.tangem.datasource.api.tangemTech.models.YieldTokenChartResponse import retrofit2.http.Body import retrofit2.http.GET +import retrofit2.http.Header import retrofit2.http.POST import retrofit2.http.Path import retrofit2.http.Query @@ -34,6 +35,7 @@ interface YieldSupplyApi { @POST("api/v1/module/activate") suspend fun activateYieldModule( @Body body: YieldSupplyChangeTokenStatusBody, + @Header("userWalletId") userWalletId: String, ): ApiResponse @POST("api/v1/module/deactivate") 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 84d2441b9e..cdc6d867fc 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 @@ -76,18 +76,22 @@ internal class DefaultYieldSupplyRepository( (walletManager as? YieldSupplyProvider)?.isSupported() ?: false } - override suspend fun activateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean = - withContext(dispatchers.io) { - val chainId = Blockchain.fromNetworkId(cryptoCurrencyToken.network.backendId)?.getChainId() - ?: error("Chain id is required for evm's") - yieldSupplyApi.activateYieldModule( - YieldSupplyChangeTokenStatusBody( - tokenAddress = cryptoCurrencyToken.contractAddress, - chainId = chainId, - userAddress = address, - ), - ).getOrThrow().isActive - } + override suspend fun activateProtocol( + userWalletId: UserWalletId, + cryptoCurrencyToken: CryptoCurrency.Token, + address: String, + ): Boolean = withContext(dispatchers.io) { + val chainId = Blockchain.fromNetworkId(cryptoCurrencyToken.network.backendId)?.getChainId() + ?: error("Chain id is required for evm's") + yieldSupplyApi.activateYieldModule( + body = YieldSupplyChangeTokenStatusBody( + tokenAddress = cryptoCurrencyToken.contractAddress, + chainId = chainId, + userAddress = address, + ), + userWalletId = userWalletId.stringValue, + ).getOrThrow().isActive + } override suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean = withContext(dispatchers.io) { 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 2a62e896fd..7fbbc6d543 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 @@ -46,7 +46,11 @@ interface YieldSupplyRepository { * May throw on network/backend errors or if required chain id cannot be resolved. */ @Throws - suspend fun activateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean + suspend fun activateProtocol( + userWalletId: UserWalletId, + cryptoCurrencyToken: CryptoCurrency.Token, + address: String, + ): Boolean /** * Deactivate yield protocol for the specified token. diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyActivateUseCase.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyActivateUseCase.kt index 5b2126f395..f91c10b983 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyActivateUseCase.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyActivateUseCase.kt @@ -2,15 +2,23 @@ package com.tangem.domain.yield.supply.usecase import arrow.core.Either import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.yield.supply.YieldSupplyRepository class YieldSupplyActivateUseCase( private val yieldSupplyRepository: YieldSupplyRepository, ) { - suspend operator fun invoke(cryptoCurrency: CryptoCurrency, address: String): Either = - Either.catch { - val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected") - yieldSupplyRepository.activateProtocol(token, address) - } + suspend operator fun invoke( + userWalletId: UserWalletId, + cryptoCurrency: CryptoCurrency, + address: String, + ): Either = Either.catch { + val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected") + yieldSupplyRepository.activateProtocol( + userWalletId = userWalletId, + cryptoCurrencyToken = token, + address = address, + ) + } } \ 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 b7e828f6fd..2360b55d2d 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 @@ -311,7 +311,11 @@ internal class YieldSupplyModel @Inject constructor( val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value ?: return modelScope.launch(dispatchers.default) { if (cryptoCurrencyStatus.value.yieldSupplyStatus?.isActive == true) { - yieldSupplyActivateUseCase(token, address).onRight { + yieldSupplyActivateUseCase( + userWalletId = userWallet.walletId, + cryptoCurrency = token, + address = address, + ).onRight { lastYieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus } } else { 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 bb8781d903..e890ae8bc5 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 @@ -278,7 +278,11 @@ internal class YieldSupplyStartEarningModel @Inject constructor( val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value if (address != null) { - yieldSupplyActivateUseCase(cryptoCurrency, address) + yieldSupplyActivateUseCase( + userWalletId = userWallet.walletId, + cryptoCurrency = cryptoCurrency, + address = address, + ) } modelScope.launch { 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 8c189f61d8..782c6b2d3e 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 @@ -37,11 +37,11 @@ internal class YieldSupplyStartEarningFeeContentTransformer( val feeFiat = feeFiatRate?.let(feeValue::multiply) val feeFiatValueText = feeFiat.format { fiat(appCurrency.code, appCurrency.symbol) } - val estimatedFeeFiat = feeFiatRate?.let(estimatedFeeValue::multiply) + val estimatedFeeFiat = estimatedFeeValue val estimatedFeeFiatValueText = estimatedFeeFiat.format { fiat(appCurrency.code, appCurrency.symbol) } val tokenCryptoFee = tokenFiatRate?.let { rate -> - estimatedFeeFiat?.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) + estimatedFeeFiat.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) } val tokenCryptoFeeValueText = tokenCryptoFee.format { crypto(cryptoCurrency) } val tokenFiatFeeValueText = estimatedFeeFiat.format { fiat(appCurrency.code, appCurrency.symbol) } From 513c04fa25896976fde0a739e151351f7ae7af59 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 7 Nov 2025 05:56:30 +0000 Subject: [PATCH 9/9] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 852b769c33..48711f2377 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,9 +5,9 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.30-1299" +tangemBlockchainSdk = "develop-1301" #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 ^