Updated on 2026-08-14
This commit is contained in:
parent
0adc20d9aa
commit
dc80c7625c
14 changed files with 405 additions and 23 deletions
|
|
@ -17,6 +17,7 @@ import com.tangem.core.ui.decompose.ComposableContentComponent
|
|||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.settings.usercountry.models.UserCountry
|
||||
import com.tangem.domain.swap.models.SwapAmountType
|
||||
import com.tangem.features.swap.v2.impl.amount.SwapAmountComponentParams.AmountBlockParams
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountUM
|
||||
import com.tangem.features.swap.v2.impl.amount.model.SwapAmountModel
|
||||
|
|
@ -82,7 +83,9 @@ internal class SwapAmountBlockComponent(
|
|||
context = childByContext(componentContext),
|
||||
params = SwapChooseProviderComponent.Params(
|
||||
providers = config.providers,
|
||||
cryptoCurrency = config.cryptoCurrency,
|
||||
fromCryptoCurrency = config.fromCryptoCurrency,
|
||||
toCryptoCurrency = config.toCryptoCurrency,
|
||||
amountType = config.amountType,
|
||||
selectedProvider = config.selectedProvider,
|
||||
userCountry = config.userCountry,
|
||||
callback = model,
|
||||
|
|
@ -93,7 +96,9 @@ internal class SwapAmountBlockComponent(
|
|||
|
||||
data class SwapChooseProviderConfig(
|
||||
val providers: ImmutableList<SwapQuoteUM>,
|
||||
val cryptoCurrency: CryptoCurrency,
|
||||
val fromCryptoCurrency: CryptoCurrency,
|
||||
val toCryptoCurrency: CryptoCurrency,
|
||||
val amountType: SwapAmountType,
|
||||
val selectedProvider: ExpressProvider,
|
||||
val userCountry: UserCountry,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -375,7 +375,12 @@ internal class SwapAmountModel @Inject constructor(
|
|||
override fun onProviderClick() {
|
||||
val amountUM = uiState.value as? SwapAmountUM.Content ?: return
|
||||
val selectedProvider = amountUM.selectedQuote.provider ?: return
|
||||
val cryptoCurrency = params.secondaryCryptoCurrency ?: return
|
||||
val secondaryStatus = amountUM.secondaryCryptoCurrencyStatus ?: return
|
||||
|
||||
val (fromCryptoCurrency, toCryptoCurrency) = amountUM.swapDirection.withSwapDirection(
|
||||
onDirect = { amountUM.primaryCryptoCurrencyStatus.currency to secondaryStatus.currency },
|
||||
onReverse = { secondaryStatus.currency to amountUM.primaryCryptoCurrencyStatus.currency },
|
||||
)
|
||||
|
||||
analyticsEventHandler.send(
|
||||
SwapAmountAnalyticEvents.ProviderSelectorClicked(
|
||||
|
|
@ -386,7 +391,9 @@ internal class SwapAmountModel @Inject constructor(
|
|||
bottomSheetNavigation.activate(
|
||||
SwapChooseProviderConfig(
|
||||
providers = amountUM.swapQuotes,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
fromCryptoCurrency = fromCryptoCurrency,
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
amountType = amountUM.selectedAmountType,
|
||||
selectedProvider = selectedProvider,
|
||||
userCountry = userCountry,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
|||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.settings.usercountry.models.UserCountry
|
||||
import com.tangem.domain.swap.models.SwapAmountType
|
||||
import com.tangem.features.swap.v2.impl.chooseprovider.model.SwapChooseProviderModel
|
||||
import com.tangem.features.swap.v2.impl.chooseprovider.ui.SwapChooseProviderBottomSheet
|
||||
import com.tangem.features.swap.v2.impl.chooseprovider.ui.SwapChooseProviderContent
|
||||
|
|
@ -49,7 +50,9 @@ internal class SwapChooseProviderComponent(
|
|||
}
|
||||
|
||||
data class Params(
|
||||
val cryptoCurrency: CryptoCurrency,
|
||||
val fromCryptoCurrency: CryptoCurrency,
|
||||
val toCryptoCurrency: CryptoCurrency,
|
||||
val amountType: SwapAmountType,
|
||||
val selectedProvider: ExpressProvider,
|
||||
val providers: ImmutableList<SwapQuoteUM>,
|
||||
val userCountry: UserCountry,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ internal class SwapChooseProviderModel @Inject constructor(
|
|||
|
||||
private val swapProviderListItemConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
SwapProviderListItemConverter(
|
||||
cryptoCurrency = params.cryptoCurrency,
|
||||
fromCryptoCurrency = params.fromCryptoCurrency,
|
||||
toCryptoCurrency = params.toCryptoCurrency,
|
||||
amountType = params.amountType,
|
||||
selectedProvider = params.selectedProvider,
|
||||
isNeedApplyFCARestrictions = isNeedApplyFCARestrictions,
|
||||
needBestRateBadge = params.providers.filterIsInstance<SwapQuoteUM.Content>().isSingleItem().not(),
|
||||
|
|
|
|||
|
|
@ -12,21 +12,33 @@ import com.tangem.core.ui.format.bigdecimal.format
|
|||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.swap.models.SwapAmountType
|
||||
import com.tangem.features.swap.v2.impl.R
|
||||
import com.tangem.features.swap.v2.impl.chooseprovider.entity.SwapProviderListItem
|
||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
||||
import com.tangem.features.swap.v2.impl.common.isRestrictedByFCA
|
||||
import com.tangem.features.swap.v2.impl.common.resolveAmountErrorCurrency
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
internal class SwapProviderListItemConverter(
|
||||
private val cryptoCurrency: CryptoCurrency,
|
||||
private val fromCryptoCurrency: CryptoCurrency,
|
||||
private val toCryptoCurrency: CryptoCurrency,
|
||||
private val amountType: SwapAmountType,
|
||||
private val selectedProvider: ExpressProvider,
|
||||
private val isNeedApplyFCARestrictions: Boolean,
|
||||
needBestRateBadge: Boolean,
|
||||
) : Converter<SwapQuoteUM, SwapProviderListItem?> {
|
||||
|
||||
private val amountErrorCurrency: CryptoCurrency = resolveAmountErrorCurrency(
|
||||
fromCryptoCurrency = fromCryptoCurrency,
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
amountType = amountType,
|
||||
)
|
||||
|
||||
private val providerStateConverter = SwapProviderStateConverter(
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
fromCryptoCurrency = fromCryptoCurrency,
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
amountType = amountType,
|
||||
selectedProvider = selectedProvider,
|
||||
isNeedApplyFCARestrictions = isNeedApplyFCARestrictions,
|
||||
isNeedBestRateBadge = needBestRateBadge,
|
||||
|
|
@ -63,7 +75,7 @@ internal class SwapProviderListItemConverter(
|
|||
is ExpressError.AmountError.TooSmallError -> resourceReference(
|
||||
id = R.string.express_provider_min_amount,
|
||||
formatArgs = wrappedList(
|
||||
error.amount.format { crypto(cryptoCurrency) },
|
||||
error.amount.format { crypto(amountErrorCurrency) },
|
||||
),
|
||||
)
|
||||
is ExpressError.AmountError.NotEnoughAllowanceError,
|
||||
|
|
@ -71,7 +83,7 @@ internal class SwapProviderListItemConverter(
|
|||
-> resourceReference(
|
||||
id = R.string.express_provider_max_amount,
|
||||
formatArgs = wrappedList(
|
||||
error.amount.format { crypto(cryptoCurrency) },
|
||||
error.amount.format { crypto(amountErrorCurrency) },
|
||||
),
|
||||
)
|
||||
else -> TextReference.EMPTY
|
||||
|
|
|
|||
|
|
@ -8,21 +8,31 @@ import com.tangem.core.ui.format.bigdecimal.format
|
|||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.swap.models.SwapAmountType
|
||||
import com.tangem.features.swap.v2.impl.R
|
||||
import com.tangem.features.swap.v2.impl.chooseprovider.entity.SwapProviderState
|
||||
import com.tangem.features.swap.v2.impl.chooseprovider.entity.SwapProviderState.AdditionalBadge
|
||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
||||
import com.tangem.features.swap.v2.impl.common.isRestrictedByFCA
|
||||
import com.tangem.features.swap.v2.impl.common.resolveAmountErrorCurrency
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
@Deprecated("Remove with new design")
|
||||
internal class SwapProviderStateConverter(
|
||||
private val cryptoCurrency: CryptoCurrency,
|
||||
private val fromCryptoCurrency: CryptoCurrency,
|
||||
private val toCryptoCurrency: CryptoCurrency,
|
||||
private val amountType: SwapAmountType,
|
||||
private val selectedProvider: ExpressProvider,
|
||||
private val isNeedBestRateBadge: Boolean,
|
||||
private val isNeedApplyFCARestrictions: Boolean,
|
||||
) : Converter<SwapQuoteUM, SwapProviderState> {
|
||||
|
||||
private val amountErrorCurrency: CryptoCurrency = resolveAmountErrorCurrency(
|
||||
fromCryptoCurrency = fromCryptoCurrency,
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
amountType = amountType,
|
||||
)
|
||||
|
||||
override fun convert(value: SwapQuoteUM): SwapProviderState {
|
||||
return when (value) {
|
||||
is SwapQuoteUM.Content -> value.convertToContent()
|
||||
|
|
@ -71,7 +81,7 @@ internal class SwapProviderStateConverter(
|
|||
is ExpressError.AmountError.TooSmallError -> resourceReference(
|
||||
id = R.string.express_provider_min_amount,
|
||||
formatArgs = wrappedList(
|
||||
error.amount.format { crypto(cryptoCurrency) },
|
||||
error.amount.format { crypto(amountErrorCurrency) },
|
||||
),
|
||||
)
|
||||
is ExpressError.AmountError.NotEnoughAllowanceError,
|
||||
|
|
@ -79,7 +89,7 @@ internal class SwapProviderStateConverter(
|
|||
-> resourceReference(
|
||||
id = R.string.express_provider_max_amount,
|
||||
formatArgs = wrappedList(
|
||||
error.amount.format { crypto(cryptoCurrency) },
|
||||
error.amount.format { crypto(amountErrorCurrency) },
|
||||
),
|
||||
)
|
||||
else -> TextReference.EMPTY
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.features.swap.v2.impl.common
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.swap.models.SwapAmountType
|
||||
|
||||
internal fun resolveAmountErrorCurrency(
|
||||
fromCryptoCurrency: CryptoCurrency,
|
||||
toCryptoCurrency: CryptoCurrency,
|
||||
amountType: SwapAmountType?,
|
||||
): CryptoCurrency = when (amountType) {
|
||||
SwapAmountType.To -> toCryptoCurrency
|
||||
SwapAmountType.From, null -> fromCryptoCurrency
|
||||
}
|
||||
|
|
@ -7,10 +7,10 @@ import com.tangem.core.decompose.context.AppComponentContext
|
|||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.express.models.ExpressRateType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.swap.models.SwapAmountType
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.PriceImpact
|
||||
import java.math.BigDecimal
|
||||
import com.tangem.features.swap.v2.impl.notifications.model.SwapNotificationsModel
|
||||
|
|
@ -54,7 +54,7 @@ internal class SwapNotificationsComponent(
|
|||
val fromCryptoCurrencyStatus: CryptoCurrencyStatus? = null,
|
||||
val priceImpact: PriceImpact? = null,
|
||||
val provider: ExpressProvider? = null,
|
||||
val rateType: ExpressRateType? = null,
|
||||
val amountType: SwapAmountType? = null,
|
||||
val shouldIncludeFeeInBalanceCheck: Boolean = false,
|
||||
val feeValue: BigDecimal? = null,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ import com.tangem.core.decompose.model.ParamsContainer
|
|||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressRateType
|
||||
import com.tangem.domain.transaction.usecase.IsMemoRequiredUseCase
|
||||
import com.tangem.features.swap.v2.api.subcomponents.SwapAmountUpdateTrigger
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.PriceImpact
|
||||
import com.tangem.features.swap.v2.impl.common.resolveAmountErrorCurrency
|
||||
import com.tangem.features.swap.v2.impl.notifications.DefaultSwapNotificationsUpdateTrigger
|
||||
import com.tangem.features.swap.v2.impl.notifications.SwapNotificationsComponent
|
||||
import com.tangem.features.swap.v2.impl.notifications.SwapNotificationsComponent.Params.SwapNotificationData
|
||||
|
|
@ -152,11 +152,11 @@ internal class SwapNotificationsModel @Inject constructor(
|
|||
val fromCryptoCurrency = notificationData.fromCryptoCurrency ?: return
|
||||
val toCryptoCurrency = notificationData.toCryptoCurrencyStatus?.currency ?: return
|
||||
|
||||
val amountErrorCurrency = if (notificationData.rateType == ExpressRateType.Fixed) {
|
||||
toCryptoCurrency
|
||||
} else {
|
||||
fromCryptoCurrency
|
||||
}
|
||||
val amountErrorCurrency = resolveAmountErrorCurrency(
|
||||
fromCryptoCurrency = fromCryptoCurrency,
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
amountType = notificationData.amountType,
|
||||
)
|
||||
|
||||
val errorNotification = when (expressError) {
|
||||
is ExpressError.AmountError.TooSmallError -> SwapNotificationUM.Error.MinimalAmountError(
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ internal class SendWithSwapConfirmComponent @AssistedInject constructor(
|
|||
enteredFromAmount = model.confirmData.enteredFromAmount,
|
||||
fromCryptoCurrencyStatus = model.confirmData.fromCryptoCurrencyStatus,
|
||||
priceImpact = model.confirmData.priceImpact,
|
||||
rateType = model.confirmData.rateType,
|
||||
amountType = model.confirmData.amountType,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -460,7 +460,7 @@ internal class SendWithSwapConfirmModel @Inject constructor(
|
|||
fromCryptoCurrencyStatus = confirmData.fromCryptoCurrencyStatus,
|
||||
priceImpact = confirmData.priceImpact,
|
||||
provider = confirmData.quote?.provider,
|
||||
rateType = confirmData.rateType,
|
||||
amountType = confirmData.amountType,
|
||||
shouldIncludeFeeInBalanceCheck = isFixedRate && isAmountSubtractAvailable,
|
||||
feeValue = confirmData.fee?.amount?.value,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,143 @@
|
|||
package com.tangem.features.swap.v2.impl.chooseprovider.model.converter
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.core.ui.components.provider.entity.ProviderChooseUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.express.models.ExpressProviderType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.swap.models.SwapAmountType
|
||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import org.junit.Test
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal class SwapProviderListItemConverterTest {
|
||||
|
||||
private val provider = ExpressProvider(
|
||||
providerId = "p1",
|
||||
name = "Test Provider",
|
||||
type = ExpressProviderType.CEX,
|
||||
imageLarge = "",
|
||||
termsOfUse = null,
|
||||
privacyPolicy = null,
|
||||
slippage = null,
|
||||
)
|
||||
|
||||
private val fromCurrency = mockk<CryptoCurrency>(relaxed = true).also {
|
||||
every { it.symbol } returns FROM_SYMBOL
|
||||
every { it.decimals } returns 18
|
||||
}
|
||||
|
||||
private val toCurrency = mockk<CryptoCurrency>(relaxed = true).also {
|
||||
every { it.symbol } returns TO_SYMBOL
|
||||
every { it.decimals } returns 8
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN quote with TooSmallError and amountType To WHEN convert THEN error text uses to symbol`() {
|
||||
// GIVEN
|
||||
val converter = buildConverter(amountType = SwapAmountType.To)
|
||||
val errorQuote = errorQuote(ExpressError.AmountError.TooSmallError(code = 1, amount = BigDecimal("1.5")))
|
||||
|
||||
// WHEN
|
||||
val item = converter.convert(errorQuote)
|
||||
|
||||
// THEN
|
||||
assertThat(item).isNotNull()
|
||||
val errorText = (item!!.providerUM.extraUM as ProviderChooseUM.ExtraUM.Error).text
|
||||
assertSymbolUsed(errorText, expectedSymbol = TO_SYMBOL, otherSymbol = FROM_SYMBOL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN quote with TooSmallError and amountType From WHEN convert THEN error text uses from symbol`() {
|
||||
// GIVEN
|
||||
val converter = buildConverter(amountType = SwapAmountType.From)
|
||||
val errorQuote = errorQuote(ExpressError.AmountError.TooSmallError(code = 1, amount = BigDecimal("1.5")))
|
||||
|
||||
// WHEN
|
||||
val item = converter.convert(errorQuote)
|
||||
|
||||
// THEN
|
||||
assertThat(item).isNotNull()
|
||||
val errorText = (item!!.providerUM.extraUM as ProviderChooseUM.ExtraUM.Error).text
|
||||
assertSymbolUsed(errorText, expectedSymbol = FROM_SYMBOL, otherSymbol = TO_SYMBOL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN quote with TooBigError and amountType To WHEN convert THEN error text uses to symbol`() {
|
||||
// GIVEN
|
||||
val converter = buildConverter(amountType = SwapAmountType.To)
|
||||
val errorQuote = errorQuote(ExpressError.AmountError.TooBigError(code = 2, amount = BigDecimal("999")))
|
||||
|
||||
// WHEN
|
||||
val item = converter.convert(errorQuote)
|
||||
|
||||
// THEN
|
||||
assertThat(item).isNotNull()
|
||||
val errorText = (item!!.providerUM.extraUM as ProviderChooseUM.ExtraUM.Error).text
|
||||
assertSymbolUsed(errorText, expectedSymbol = TO_SYMBOL, otherSymbol = FROM_SYMBOL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN quote with TooBigError and amountType From WHEN convert THEN error text uses from symbol`() {
|
||||
// GIVEN
|
||||
val converter = buildConverter(amountType = SwapAmountType.From)
|
||||
val errorQuote = errorQuote(ExpressError.AmountError.TooBigError(code = 2, amount = BigDecimal("999")))
|
||||
|
||||
// WHEN
|
||||
val item = converter.convert(errorQuote)
|
||||
|
||||
// THEN
|
||||
assertThat(item).isNotNull()
|
||||
val errorText = (item!!.providerUM.extraUM as ProviderChooseUM.ExtraUM.Error).text
|
||||
assertSymbolUsed(errorText, expectedSymbol = FROM_SYMBOL, otherSymbol = TO_SYMBOL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN quote with NotEnoughAllowanceError and amountType From WHEN convert THEN error text uses from symbol`() {
|
||||
// GIVEN
|
||||
val converter = buildConverter(amountType = SwapAmountType.From)
|
||||
val errorQuote = errorQuote(
|
||||
ExpressError.AmountError.NotEnoughAllowanceError(code = 3, amount = BigDecimal("10")),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val item = converter.convert(errorQuote)
|
||||
|
||||
// THEN
|
||||
assertThat(item).isNotNull()
|
||||
val errorText = (item!!.providerUM.extraUM as ProviderChooseUM.ExtraUM.Error).text
|
||||
assertSymbolUsed(errorText, expectedSymbol = FROM_SYMBOL, otherSymbol = TO_SYMBOL)
|
||||
}
|
||||
|
||||
private fun buildConverter(amountType: SwapAmountType): SwapProviderListItemConverter {
|
||||
return SwapProviderListItemConverter(
|
||||
fromCryptoCurrency = fromCurrency,
|
||||
toCryptoCurrency = toCurrency,
|
||||
amountType = amountType,
|
||||
selectedProvider = provider,
|
||||
isNeedApplyFCARestrictions = false,
|
||||
needBestRateBadge = false,
|
||||
)
|
||||
}
|
||||
|
||||
private fun errorQuote(error: ExpressError): SwapQuoteUM.Error = SwapQuoteUM.Error(
|
||||
provider = provider,
|
||||
expressError = error,
|
||||
)
|
||||
|
||||
private fun assertSymbolUsed(text: TextReference, expectedSymbol: String, otherSymbol: String) {
|
||||
val res = text as TextReference.Res
|
||||
val formatted = res.formatArgs.first().toString()
|
||||
assertThat(formatted).contains(expectedSymbol)
|
||||
assertThat(formatted).doesNotContain(otherSymbol)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val FROM_SYMBOL = "ETH"
|
||||
const val TO_SYMBOL = "BTC"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
package com.tangem.features.swap.v2.impl.chooseprovider.model.converter
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.express.models.ExpressProviderType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.swap.models.SwapAmountType
|
||||
import com.tangem.features.swap.v2.impl.chooseprovider.entity.SwapProviderState
|
||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import org.junit.Test
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
internal class SwapProviderStateConverterTest {
|
||||
|
||||
private val provider = ExpressProvider(
|
||||
providerId = "p1",
|
||||
name = "Test Provider",
|
||||
type = ExpressProviderType.CEX,
|
||||
imageLarge = "",
|
||||
termsOfUse = null,
|
||||
privacyPolicy = null,
|
||||
slippage = null,
|
||||
)
|
||||
|
||||
private val fromCurrency = mockk<CryptoCurrency>(relaxed = true).also {
|
||||
every { it.symbol } returns FROM_SYMBOL
|
||||
every { it.decimals } returns 18
|
||||
}
|
||||
|
||||
private val toCurrency = mockk<CryptoCurrency>(relaxed = true).also {
|
||||
every { it.symbol } returns TO_SYMBOL
|
||||
every { it.decimals } returns 8
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN error quote TooSmallError and amountType To WHEN convert THEN subtitle uses to symbol`() {
|
||||
// GIVEN
|
||||
val converter = buildConverter(amountType = SwapAmountType.To)
|
||||
val errorQuote = errorQuote(ExpressError.AmountError.TooSmallError(code = 1, amount = BigDecimal("1.5")))
|
||||
|
||||
// WHEN
|
||||
val state = converter.convert(errorQuote)
|
||||
|
||||
// THEN
|
||||
assertSymbolUsed(state, expectedSymbol = TO_SYMBOL, otherSymbol = FROM_SYMBOL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN error quote TooSmallError and amountType From WHEN convert THEN subtitle uses from symbol`() {
|
||||
// GIVEN
|
||||
val converter = buildConverter(amountType = SwapAmountType.From)
|
||||
val errorQuote = errorQuote(ExpressError.AmountError.TooSmallError(code = 1, amount = BigDecimal("1.5")))
|
||||
|
||||
// WHEN
|
||||
val state = converter.convert(errorQuote)
|
||||
|
||||
// THEN
|
||||
assertSymbolUsed(state, expectedSymbol = FROM_SYMBOL, otherSymbol = TO_SYMBOL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN error quote TooBigError and amountType To WHEN convert THEN subtitle uses to symbol`() {
|
||||
// GIVEN
|
||||
val converter = buildConverter(amountType = SwapAmountType.To)
|
||||
val errorQuote = errorQuote(ExpressError.AmountError.TooBigError(code = 2, amount = BigDecimal("999")))
|
||||
|
||||
// WHEN
|
||||
val state = converter.convert(errorQuote)
|
||||
|
||||
// THEN
|
||||
assertSymbolUsed(state, expectedSymbol = TO_SYMBOL, otherSymbol = FROM_SYMBOL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN error quote TooBigError and amountType From WHEN convert THEN subtitle uses from symbol`() {
|
||||
// GIVEN
|
||||
val converter = buildConverter(amountType = SwapAmountType.From)
|
||||
val errorQuote = errorQuote(ExpressError.AmountError.TooBigError(code = 2, amount = BigDecimal("999")))
|
||||
|
||||
// WHEN
|
||||
val state = converter.convert(errorQuote)
|
||||
|
||||
// THEN
|
||||
assertSymbolUsed(state, expectedSymbol = FROM_SYMBOL, otherSymbol = TO_SYMBOL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN error quote NotEnoughAllowanceError and amountType From WHEN convert THEN subtitle uses from symbol`() {
|
||||
// GIVEN
|
||||
val converter = buildConverter(amountType = SwapAmountType.From)
|
||||
val errorQuote = errorQuote(
|
||||
ExpressError.AmountError.NotEnoughAllowanceError(code = 3, amount = BigDecimal("10")),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val state = converter.convert(errorQuote)
|
||||
|
||||
// THEN
|
||||
assertSymbolUsed(state, expectedSymbol = FROM_SYMBOL, otherSymbol = TO_SYMBOL)
|
||||
}
|
||||
|
||||
private fun buildConverter(amountType: SwapAmountType): SwapProviderStateConverter {
|
||||
return SwapProviderStateConverter(
|
||||
fromCryptoCurrency = fromCurrency,
|
||||
toCryptoCurrency = toCurrency,
|
||||
amountType = amountType,
|
||||
selectedProvider = provider,
|
||||
isNeedBestRateBadge = false,
|
||||
isNeedApplyFCARestrictions = false,
|
||||
)
|
||||
}
|
||||
|
||||
private fun errorQuote(error: ExpressError): SwapQuoteUM.Error = SwapQuoteUM.Error(
|
||||
provider = provider,
|
||||
expressError = error,
|
||||
)
|
||||
|
||||
private fun assertSymbolUsed(state: SwapProviderState, expectedSymbol: String, otherSymbol: String) {
|
||||
val content = state as SwapProviderState.Content
|
||||
val subtitle = content.subtitle as TextReference.Res
|
||||
val formatted = subtitle.formatArgs.first().toString()
|
||||
assertThat(formatted).contains(expectedSymbol)
|
||||
assertThat(formatted).doesNotContain(otherSymbol)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val FROM_SYMBOL = "ETH"
|
||||
const val TO_SYMBOL = "BTC"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.tangem.features.swap.v2.impl.common
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.swap.models.SwapAmountType
|
||||
import io.mockk.mockk
|
||||
import org.junit.Test
|
||||
|
||||
internal class AmountErrorCurrencyResolverTest {
|
||||
|
||||
private val from = mockk<CryptoCurrency>(relaxed = true)
|
||||
private val to = mockk<CryptoCurrency>(relaxed = true)
|
||||
|
||||
@Test
|
||||
fun `GIVEN amountType From WHEN resolveAmountErrorCurrency THEN returns fromCryptoCurrency`() {
|
||||
// GIVEN, WHEN
|
||||
val result = resolveAmountErrorCurrency(
|
||||
fromCryptoCurrency = from,
|
||||
toCryptoCurrency = to,
|
||||
amountType = SwapAmountType.From,
|
||||
)
|
||||
|
||||
// THEN
|
||||
assertThat(result).isSameInstanceAs(from)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN amountType To WHEN resolveAmountErrorCurrency THEN returns toCryptoCurrency`() {
|
||||
// GIVEN, WHEN
|
||||
val result = resolveAmountErrorCurrency(
|
||||
fromCryptoCurrency = from,
|
||||
toCryptoCurrency = to,
|
||||
amountType = SwapAmountType.To,
|
||||
)
|
||||
|
||||
// THEN
|
||||
assertThat(result).isSameInstanceAs(to)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN amountType null WHEN resolveAmountErrorCurrency THEN returns fromCryptoCurrency`() {
|
||||
// GIVEN, WHEN
|
||||
val result = resolveAmountErrorCurrency(
|
||||
fromCryptoCurrency = from,
|
||||
toCryptoCurrency = to,
|
||||
amountType = null,
|
||||
)
|
||||
|
||||
// THEN
|
||||
assertThat(result).isSameInstanceAs(from)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue