Updated on 2026-08-14
This commit is contained in:
parent
aa9956d69f
commit
8cee77705f
7 changed files with 80 additions and 6 deletions
|
|
@ -219,4 +219,10 @@ internal object YieldSupplyDomainModule {
|
|||
yieldSupplyRepository = yieldSupplyRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideYieldSupplyGetDustMinAmountUseCase(): YieldSupplyGetDustMinAmountUseCase {
|
||||
return YieldSupplyGetDustMinAmountUseCase()
|
||||
}
|
||||
}
|
||||
|
|
@ -11,9 +11,9 @@ fun CryptoCurrencyStatus.hasNotSuppliedAmount(): Boolean {
|
|||
return notSupplied > BigDecimal.ZERO
|
||||
}
|
||||
|
||||
fun CryptoCurrencyStatus.shouldShowNotSuppliedInfoIcon(minAmount: BigDecimal): Boolean {
|
||||
fun CryptoCurrencyStatus.shouldShowNotSuppliedInfoIcon(dustAmount: BigDecimal): Boolean {
|
||||
val notSupplied = notSuppliedAmountOrNull() ?: return false
|
||||
return notSupplied >= minAmount
|
||||
return notSupplied >= dustAmount
|
||||
}
|
||||
|
||||
fun CryptoCurrencyStatus.notSuppliedAmountOrNull(): BigDecimal? {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.domain.yield.supply.usecase
|
||||
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import java.math.BigDecimal
|
||||
|
||||
class YieldSupplyGetDustMinAmountUseCase {
|
||||
|
||||
operator fun invoke(minAmount: BigDecimal, appCurrency: AppCurrency): BigDecimal {
|
||||
return if (appCurrency.code in SUPPORTED_DUST_CURRENCIES) {
|
||||
DUST_MIN_AMOUNT
|
||||
} else {
|
||||
minAmount.stripTrailingZeros()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val DUST_MIN_AMOUNT = BigDecimal("0.1")
|
||||
private val SUPPORTED_DUST_CURRENCIES = setOf("EUR", "USD", "AUD", "CAD", "GBP")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.tangem.domain.yield.supply.usecase
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.math.BigDecimal
|
||||
|
||||
class YieldSupplyGetDustMinAmountUseCaseTest {
|
||||
|
||||
private val useCase = YieldSupplyGetDustMinAmountUseCase()
|
||||
|
||||
@Test
|
||||
fun `GIVEN supported currency WHEN invoke THEN return dust min amount`() {
|
||||
val minAmount = BigDecimal("123.456")
|
||||
val appCurrency = AppCurrency(code = "EUR", name = "Euro", symbol = "€")
|
||||
|
||||
val result = useCase(minAmount, appCurrency)
|
||||
|
||||
assertThat(result).isEqualTo(BigDecimal("0.1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN unsupported currency WHEN invoke THEN return min amount stripped`() {
|
||||
val minAmount = BigDecimal("1.2300")
|
||||
val appCurrency = AppCurrency(code = "JPY", name = "Japanese Yen", symbol = "¥")
|
||||
|
||||
val result = useCase(minAmount, appCurrency)
|
||||
|
||||
assertThat(result).isEqualTo(BigDecimal("1.23"))
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +58,7 @@ internal class YieldSupplyActiveModel @Inject constructor(
|
|||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val appRouter: AppRouter,
|
||||
private val yieldSupplyGetDustMinAmountUseCase: YieldSupplyGetDustMinAmountUseCase,
|
||||
) : Model(), YieldSupplyStopEarningComponent.ModelCallback,
|
||||
YieldSupplyApproveComponent.ModelCallback {
|
||||
|
||||
|
|
@ -241,11 +242,13 @@ internal class YieldSupplyActiveModel @Inject constructor(
|
|||
userWalletId,
|
||||
cryptoCurrencyStatusFlow.value,
|
||||
).onRight { minAmount ->
|
||||
val dustAmount = yieldSupplyGetDustMinAmountUseCase(minAmount = minAmount, appCurrency = appCurrency)
|
||||
uiState.update(
|
||||
YieldSupplyActiveMinAmountTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatusFlow.value,
|
||||
appCurrency = appCurrency,
|
||||
minAmount = minAmount,
|
||||
dustMinAmount = dustAmount,
|
||||
analyticsHandler = analyticsHandler,
|
||||
onApprove = ::onApprove,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -28,11 +28,12 @@ import java.math.BigDecimal
|
|||
* - Builds the fee policy note text using the minimum amount.
|
||||
* - Adds contextual notifications:
|
||||
* - Approval required notification when spending is not yet allowed (emits analytics on CTA).
|
||||
* - "Not all amount supplied" info when wallet balance exceeds the supplied balance by more than [minAmount].
|
||||
* - "Not all amount supplied" info when the not-supplied balance exceeds the dust threshold [dustMinAmount].
|
||||
*
|
||||
* @property cryptoCurrencyStatus Current currency status used to calculate values and flags.
|
||||
* @property appCurrency Preferred fiat currency for formatting.
|
||||
* @property minAmount Protocol-required minimal amount to deposit/supply (in crypto units).
|
||||
* @property dustMinAmount Threshold used to detect dust/not-supplied balance (in crypto units).
|
||||
* @property analyticsHandler Analytics reporter for user actions.
|
||||
* @property onApprove Action invoked when the "Approve" notification button is tapped.
|
||||
*/
|
||||
|
|
@ -40,6 +41,7 @@ internal class YieldSupplyActiveMinAmountTransformer(
|
|||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val appCurrency: AppCurrency,
|
||||
private val minAmount: BigDecimal,
|
||||
private val dustMinAmount: BigDecimal,
|
||||
private val analyticsHandler: AnalyticsEventHandler,
|
||||
private val onApprove: () -> Unit,
|
||||
) : Transformer<YieldSupplyActiveContentUM> {
|
||||
|
|
@ -89,7 +91,7 @@ internal class YieldSupplyActiveMinAmountTransformer(
|
|||
}
|
||||
|
||||
private fun getNotSuppliedNotification(cryptoCurrencyStatus: CryptoCurrencyStatus): NotificationUM? {
|
||||
return if (cryptoCurrencyStatus.shouldShowNotSuppliedInfoIcon(minAmount)) {
|
||||
return if (cryptoCurrencyStatus.shouldShowNotSuppliedInfoIcon(dustMinAmount)) {
|
||||
val cryptoCurrency = cryptoCurrencyStatus.currency
|
||||
val notDepositedAmount = cryptoCurrencyStatus.notSuppliedAmountOrNull()
|
||||
val formattedAmount =
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.yield.supply.impl.main.model
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import android.os.SystemClock
|
||||
import com.tangem.common.routing.AppRoute.YieldSupplyPromo
|
||||
|
|
@ -12,6 +13,8 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.extensions.combinedReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
|
|
@ -28,6 +31,7 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyActivateUseCase
|
|||
import com.tangem.domain.yield.supply.usecase.YieldSupplyDeactivateUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyIsAvailableUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetDustMinAmountUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyMinAmountUseCase
|
||||
import com.tangem.features.yield.supply.api.YieldSupplyComponent
|
||||
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
|
||||
|
|
@ -55,6 +59,7 @@ internal class YieldSupplyModel @Inject constructor(
|
|||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
private val appRouter: AppRouter,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
|
|
@ -65,6 +70,7 @@ internal class YieldSupplyModel @Inject constructor(
|
|||
private val yieldSupplyDeactivateUseCase: YieldSupplyDeactivateUseCase,
|
||||
private val yieldSupplyRepository: YieldSupplyRepository,
|
||||
private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase,
|
||||
private val yieldSupplyGetDustMinAmountUseCase: YieldSupplyGetDustMinAmountUseCase,
|
||||
) : Model(), YieldSupplyClickIntents {
|
||||
|
||||
private val params = paramsContainer.require<YieldSupplyComponent.Params>()
|
||||
|
|
@ -73,6 +79,7 @@ internal class YieldSupplyModel @Inject constructor(
|
|||
field = MutableStateFlow<YieldSupplyUM>(YieldSupplyUM.Initial)
|
||||
|
||||
private val cryptoCurrency = params.cryptoCurrency
|
||||
private var appCurrency: AppCurrency = AppCurrency.Default
|
||||
var userWallet: UserWallet by Delegates.notNull()
|
||||
|
||||
private val fetchCurrencyJobHolder = JobHolder()
|
||||
|
|
@ -85,7 +92,8 @@ internal class YieldSupplyModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun checkIfYieldSupplyIsAvailable() {
|
||||
modelScope.launch(dispatchers.io) {
|
||||
modelScope.launch(dispatchers.default) {
|
||||
appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default }
|
||||
val isAvailable = yieldSupplyIsAvailableUseCase(params.userWalletId, params.cryptoCurrency)
|
||||
if (isAvailable) {
|
||||
subscribeOnCurrencyStatusUpdates()
|
||||
|
|
@ -345,7 +353,11 @@ internal class YieldSupplyModel @Inject constructor(
|
|||
val minAmount = yieldSupplyMinAmountUseCase(userWalletId = userWallet.walletId, cryptoCurrencyStatus)
|
||||
.getOrNull()
|
||||
if (minAmount != null) {
|
||||
cryptoCurrencyStatus.shouldShowNotSuppliedInfoIcon(minAmount)
|
||||
val dustAmount = yieldSupplyGetDustMinAmountUseCase(
|
||||
minAmount = minAmount,
|
||||
appCurrency = appCurrency,
|
||||
)
|
||||
cryptoCurrencyStatus.shouldShowNotSuppliedInfoIcon(dustAmount)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue