Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-12 20:32:25 +01:00
parent 7e42240fc6
commit bcd4838105
5 changed files with 138 additions and 15 deletions

View file

@ -38,6 +38,7 @@ internal class SwapTransferStateBuilder @Inject constructor() {
): SwapStateHolder {
val fromTokenSwapInfo = transferState.fromTokenInfo
val toTokenSwapInfo = transferState.toTokenInfo
val isInsufficientBalance = transferState.isInsufficientBalance
return uiStateHolder.copy(
sendCardData = createSendSwapCardState(
actions = actions,
@ -46,6 +47,7 @@ internal class SwapTransferStateBuilder @Inject constructor() {
isAccountsMode = transferState.isAccountsMode,
isFromCard = true,
isBalanceHidden = transferState.isBalanceHidden,
isInsufficientBalance = isInsufficientBalance,
),
receiveCardData = createSendSwapCardState(
actions = actions,
@ -54,10 +56,12 @@ internal class SwapTransferStateBuilder @Inject constructor() {
isAccountsMode = transferState.isAccountsMode,
isFromCard = false,
isBalanceHidden = transferState.isBalanceHidden,
isInsufficientBalance = isInsufficientBalance,
),
isInsufficientFunds = isInsufficientBalance,
swapButton = SwapButton(
walletInteractionIcon = walletInterationIcon(transferState.userWallet),
isEnabled = false,
isEnabled = !isInsufficientBalance,
mode = SwapButton.Mode.TRANSFER,
onClick = actions.onTransferClick,
),
@ -72,6 +76,7 @@ internal class SwapTransferStateBuilder @Inject constructor() {
isAccountsMode: Boolean,
isFromCard: Boolean,
isBalanceHidden: Boolean,
isInsufficientBalance: Boolean,
): SwapCardState {
val swapCurrencyStatus = tokenSwapInfo.swapCurrencyStatus
val formattedSwapAmount = tokenSwapInfo.tokenAmount.formatToUIRepresentation()
@ -82,6 +87,7 @@ internal class SwapTransferStateBuilder @Inject constructor() {
swapCurrencyStatus = tokenSwapInfo.swapCurrencyStatus,
isAccountsMode = isAccountsMode,
isFromCard = isFromCard,
isInsufficientBalance = isInsufficientBalance,
),
currencyIconState = iconConverter.convert(
value = swapCurrencyStatus.status,
@ -105,17 +111,27 @@ internal class SwapTransferStateBuilder @Inject constructor() {
swapCurrencyStatus: SwapCurrencyStatus,
isAccountsMode: Boolean,
isFromCard: Boolean,
isInsufficientBalance: Boolean,
): TransactionCardType {
val type = if (isFromCard) {
TransactionCardType.Inputtable(
onAmountChanged = actions.onAmountChanged,
onFocusChanged = actions.onAmountSelected,
inputError = TransactionCardType.InputError.Empty,
accountTitleUM = getCardAccountTitle(
val accountTitleUM = if (isInsufficientBalance) {
AccountTitleUM.Text(resourceReference(R.string.swapping_insufficient_funds))
} else {
getCardAccountTitle(
account = swapCurrencyStatus.account,
isAccountsMode = isAccountsMode,
isFromCard = true,
),
)
}
TransactionCardType.Inputtable(
onAmountChanged = actions.onAmountChanged,
onFocusChanged = actions.onAmountSelected,
inputError = if (isInsufficientBalance) {
TransactionCardType.InputError.InsufficientFunds
} else {
TransactionCardType.InputError.Empty
},
accountTitleUM = accountTitleUM,
isEnabled = true,
)
} else {

View file

@ -19,7 +19,6 @@ import com.tangem.feature.swap.domain.models.SwapAmount
import com.tangem.feature.swap.domain.models.ui.PriceImpact
import com.tangem.feature.swap.domain.models.ui.SwapState
import com.tangem.feature.swap.domain.models.ui.TokenSwapInfo
import com.tangem.feature.swap.domain.models.ui.TxFeeState
import com.tangem.feature.swap.models.*
import com.tangem.feature.swap.models.states.ProviderState
import com.tangem.feature.swap.presentation.R
@ -105,6 +104,62 @@ internal class SwapTransferStateBuilderTest {
)
}
@Test
fun `GIVEN insufficient balance and accounts mode disabled WHEN createTransferState THEN from card shows insufficient funds title and error and swap is disabled`() {
val transferState = buildTransferState(
fromAmount = BigDecimal("10"),
toAmount = BigDecimal("10"),
isAccountsMode = false,
isInsufficientBalance = true,
)
val result = sut.createTransferState(actions, transferState, baseStateHolder())
val sendType = (result.sendCardData as SwapCardState.SwapCardData).type as TransactionCardType.Inputtable
val receiveType = (result.receiveCardData as SwapCardState.SwapCardData).type as TransactionCardType.ReadOnly
assertThat(sendType.accountTitleUM).isEqualTo(
AccountTitleUM.Text(resourceReference(R.string.swapping_insufficient_funds)),
)
assertThat(sendType.inputError).isEqualTo(TransactionCardType.InputError.InsufficientFunds)
assertThat(receiveType.accountTitleUM).isEqualTo(
AccountTitleUM.Text(resourceReference(R.string.swapping_to_title)),
)
assertThat(result.isInsufficientFunds).isTrue()
assertThat(result.swapButton.isEnabled).isFalse()
assertThat(result.swapButton.mode).isEqualTo(SwapButton.Mode.TRANSFER)
}
@Test
fun `GIVEN insufficient balance and accounts mode enabled WHEN createTransferState THEN from card overrides Account title with insufficient funds text`() {
val transferState = buildTransferState(
fromAmount = BigDecimal("10"),
toAmount = BigDecimal("10"),
isAccountsMode = true,
isInsufficientBalance = true,
)
val result = sut.createTransferState(actions, transferState, baseStateHolder())
val portfolioAccount = toCurrencyStatus.account as Account.CryptoPortfolio
val expectedAccountIcon = CryptoPortfolioIconConverter.convert(portfolioAccount.icon)
val expectedAccountName = portfolioAccount.accountName.toUM().value
val sendType = (result.sendCardData as SwapCardState.SwapCardData).type as TransactionCardType.Inputtable
val receiveType = (result.receiveCardData as SwapCardState.SwapCardData).type as TransactionCardType.ReadOnly
assertThat(sendType.accountTitleUM).isEqualTo(
AccountTitleUM.Text(resourceReference(R.string.swapping_insufficient_funds)),
)
assertThat(sendType.inputError).isEqualTo(TransactionCardType.InputError.InsufficientFunds)
assertThat(receiveType.accountTitleUM).isEqualTo(
AccountTitleUM.Account(
prefixText = resourceReference(R.string.swapping_to_account_title),
name = expectedAccountName,
icon = expectedAccountIcon,
),
)
assertThat(result.isInsufficientFunds).isTrue()
assertThat(result.swapButton.isEnabled).isFalse()
}
private fun assertSharedCardShape(
result: SwapStateHolder,
transferState: SwapState.Transfer,
@ -128,7 +183,7 @@ internal class SwapTransferStateBuilderTest {
assertThat(result.swapButton).isEqualTo(
SwapButton(
walletInteractionIcon = walletInterationIcon(transferState.userWallet),
isEnabled = false,
isEnabled = !transferState.isInsufficientBalance,
mode = SwapButton.Mode.TRANSFER,
onClick = actions.onTransferClick,
),
@ -139,6 +194,7 @@ internal class SwapTransferStateBuilderTest {
fromAmount: BigDecimal,
toAmount: BigDecimal,
isAccountsMode: Boolean,
isInsufficientBalance: Boolean = false,
): SwapState.Transfer {
val fromInfo = TokenSwapInfo(
tokenAmount = SwapAmount(value = fromAmount, decimals = fromCurrencyStatus.currency.decimals),
@ -154,7 +210,7 @@ internal class SwapTransferStateBuilderTest {
userWallet = coldWallet,
fromTokenInfo = fromInfo,
toTokenInfo = toInfo,
txFee = TxFeeState.Empty,
isInsufficientBalance = isInsufficientBalance,
appCurrency = AppCurrency.Default,
isBalanceHidden = false,
isAccountsMode = isAccountsMode,