Updated on 2026-08-14
This commit is contained in:
parent
abd604f9f1
commit
802b914e78
8 changed files with 57 additions and 37 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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<BigDecimal, BigDecimal> 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<Throwable, Pair<BigDecimal, BigDecimal>> = catch {
|
||||
): Either<Throwable, YieldSupplyMaxFee> = 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(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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<YieldSupplyActiveContentUM> {
|
||||
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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<BigDecimal, BigDecimal>? {
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -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<TransactionData.Uncompiled>,
|
||||
private val feeValue: BigDecimal,
|
||||
private val maxNetworkFee: BigDecimal,
|
||||
private val maxNetworkFeeFiat: BigDecimal,
|
||||
private val maxNetworkFee: YieldSupplyMaxFee,
|
||||
private val minAmount: BigDecimal,
|
||||
) : Transformer<YieldSupplyActionUM> {
|
||||
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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue