Updated on 2026-08-14
This commit is contained in:
parent
62d1577a00
commit
9b101c4238
11 changed files with 167 additions and 20 deletions
|
|
@ -60,6 +60,7 @@ sealed interface SwapState {
|
|||
val currencyCheck: CryptoCurrencyCheck? = null,
|
||||
val validationResult: Throwable? = null,
|
||||
val minAdaValue: BigDecimal? = null,
|
||||
val hasRequiredTrustline: Boolean = false,
|
||||
) : SwapState
|
||||
|
||||
data class EmptyAmountState(
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.tangem.domain.notifications.IncrementNotificationsShowCountUseCase
|
|||
import com.tangem.domain.pay.WithdrawalResult
|
||||
import com.tangem.domain.swap.models.SwapCurrencyStatus
|
||||
import com.tangem.domain.tangempay.TangemPayWithdrawUseCase
|
||||
import com.tangem.domain.tokens.GetAssetRequirementsUseCase
|
||||
import com.tangem.domain.tokens.GetBalanceNotEnoughForFeeWarningUseCase
|
||||
import com.tangem.domain.tokens.GetCurrencyCheckUseCase
|
||||
import com.tangem.domain.tokens.IsAmountSubtractAvailableUseCase
|
||||
|
|
@ -31,6 +32,7 @@ import com.tangem.domain.tokens.model.warnings.CryptoCurrencyCheck
|
|||
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
import com.tangem.domain.transaction.models.AssetRequirementsCondition
|
||||
import com.tangem.domain.transaction.models.TransactionFeeExtended
|
||||
import com.tangem.domain.transaction.usecase.CreateTransferTransactionUseCase
|
||||
import com.tangem.domain.transaction.usecase.GetFeeUseCase
|
||||
|
|
@ -66,8 +68,10 @@ class SwapTransferInteractorImpl @Inject constructor(
|
|||
private val getBalanceNotEnoughForFeeWarningUseCase: GetBalanceNotEnoughForFeeWarningUseCase,
|
||||
private val getTronFeeNotificationShowCountUseCase: GetTronFeeNotificationShowCountUseCase,
|
||||
private val incrementNotificationsShowCountUseCase: IncrementNotificationsShowCountUseCase,
|
||||
private val getAssetRequirementsUseCase: GetAssetRequirementsUseCase,
|
||||
) : SwapTransferInteractor {
|
||||
|
||||
@Suppress("LongMethod")
|
||||
override suspend fun updateTransfer(
|
||||
fromSwapCurrencyStatus: SwapCurrencyStatus,
|
||||
toSwapCurrencyStatus: SwapCurrencyStatus,
|
||||
|
|
@ -109,6 +113,7 @@ class SwapTransferInteractorImpl @Inject constructor(
|
|||
amount = fromTokenAmountValue,
|
||||
fee = warningsFee,
|
||||
feeCurrencyBalanceAfterTransaction = null,
|
||||
recipientAddress = toSwapCurrencyStatus.destinationAddress(),
|
||||
)
|
||||
val isAmountSubtractAvailable = isAmountSubtractAvailable(
|
||||
userWalletId = userWallet.walletId,
|
||||
|
|
@ -130,6 +135,10 @@ class SwapTransferInteractorImpl @Inject constructor(
|
|||
)
|
||||
}
|
||||
val tronFeeNotificationShowCount = getTronFeeNotificationShowCountUseCase()
|
||||
val hasRequiredTrustline = getAssetRequirementsUseCase(
|
||||
userWalletId = toSwapCurrencyStatus.userWalletId,
|
||||
currency = toToken,
|
||||
).getOrNull() is AssetRequirementsCondition.RequiredTrustline
|
||||
return SwapState.Transfer(
|
||||
userWallet = userWallet,
|
||||
fromTokenInfo = fromTokenInfo,
|
||||
|
|
@ -145,6 +154,7 @@ class SwapTransferInteractorImpl @Inject constructor(
|
|||
isAmountSubtractAvailable = isAmountSubtractAvailable,
|
||||
isSendingAmountLoading = coverageState.isSendingAmountLoading,
|
||||
currencyCheck = currencyCheck,
|
||||
hasRequiredTrustline = hasRequiredTrustline,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.tangem.domain.notifications.IncrementNotificationsShowCountUseCase
|
|||
import com.tangem.domain.pay.WithdrawalResult
|
||||
import com.tangem.domain.swap.models.SwapCurrencyStatus
|
||||
import com.tangem.domain.tangempay.TangemPayWithdrawUseCase
|
||||
import com.tangem.domain.tokens.GetAssetRequirementsUseCase
|
||||
import com.tangem.domain.tokens.GetBalanceNotEnoughForFeeWarningUseCase
|
||||
import com.tangem.domain.tokens.GetCurrencyCheckUseCase
|
||||
import com.tangem.domain.tokens.IsAmountSubtractAvailableUseCase
|
||||
|
|
@ -42,6 +43,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -65,6 +67,7 @@ internal class SwapTransferInteractorImplTest {
|
|||
private val getBalanceNotEnoughForFeeWarningUseCase: GetBalanceNotEnoughForFeeWarningUseCase = mockk(relaxed = true)
|
||||
private val getTronFeeNotificationShowCountUseCase: GetTronFeeNotificationShowCountUseCase = mockk(relaxed = true)
|
||||
private val incrementNotificationsShowCountUseCase: IncrementNotificationsShowCountUseCase = mockk(relaxed = true)
|
||||
private val getAssetRequirementsUseCase: GetAssetRequirementsUseCase = mockk()
|
||||
|
||||
private val sut = SwapTransferInteractorImpl(
|
||||
swapFeatureToggles = swapFeatureToggles,
|
||||
|
|
@ -82,8 +85,14 @@ internal class SwapTransferInteractorImplTest {
|
|||
getBalanceNotEnoughForFeeWarningUseCase = getBalanceNotEnoughForFeeWarningUseCase,
|
||||
getTronFeeNotificationShowCountUseCase = getTronFeeNotificationShowCountUseCase,
|
||||
incrementNotificationsShowCountUseCase = incrementNotificationsShowCountUseCase,
|
||||
getAssetRequirementsUseCase = getAssetRequirementsUseCase,
|
||||
)
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
coEvery { getAssetRequirementsUseCase(any(), any()) } returns null.right()
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
clearAllMocks()
|
||||
|
|
@ -429,6 +438,68 @@ internal class SwapTransferInteractorImplTest {
|
|||
assertThat(result.isSendingAmountLoading).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN destination address WHEN updateTransfer THEN currency check requested with recipient and isAccountFunded flows through`() =
|
||||
runTest {
|
||||
// Arrange
|
||||
val appCurrency = AppCurrency(code = "USD", name = "US Dollar", symbol = "$")
|
||||
val userWallet: UserWallet = mockk(relaxed = true)
|
||||
val fromCurrencyStatus = buildCurrencyStatus(
|
||||
rawCurrencyId = FROM_RAW_CURRENCY_ID,
|
||||
decimals = FROM_DECIMALS,
|
||||
fiatRate = BigDecimal.TEN,
|
||||
amount = BigDecimal("1.6"),
|
||||
userWallet = userWallet,
|
||||
)
|
||||
val toCurrencyStatus = buildCurrencyStatus(
|
||||
rawCurrencyId = TO_RAW_CURRENCY_ID,
|
||||
decimals = TO_DECIMALS,
|
||||
userWallet = userWallet,
|
||||
destinationAddress = DESTINATION_ADDRESS,
|
||||
)
|
||||
every { getSelectedAppCurrencyUseCase() } returns flowOf(appCurrency.right())
|
||||
every { getBalanceHidingSettingsUseCase.isBalanceHidden() } returns flowOf(false)
|
||||
coEvery { isAccountsModeEnabledUseCase.invokeSync() } returns false
|
||||
// Stub matches only when the destination address is forwarded as recipientAddress; the
|
||||
// returned check has isAccountFunded = true (buildCurrencyCheck default).
|
||||
val fundedCheck = buildCurrencyCheck()
|
||||
coEvery {
|
||||
getCurrencyCheckUseCase(
|
||||
userWalletId = any(),
|
||||
currencyStatus = any(),
|
||||
feeCurrencyStatus = any(),
|
||||
amount = any(),
|
||||
fee = any(),
|
||||
feeCurrencyBalanceAfterTransaction = any(),
|
||||
recipientAddress = DESTINATION_ADDRESS,
|
||||
)
|
||||
} returns fundedCheck
|
||||
coEvery { isAmountSubtractAvailableUseCase(any(), any(), any()) } returns false.right()
|
||||
|
||||
// Act
|
||||
val result = sut.updateTransfer(
|
||||
fromSwapCurrencyStatus = fromCurrencyStatus,
|
||||
toSwapCurrencyStatus = toCurrencyStatus,
|
||||
fromTokenAmount = "1,5",
|
||||
feePaidCurrencyStatus = null,
|
||||
fee = null,
|
||||
) as SwapState.Transfer
|
||||
|
||||
// Assert
|
||||
assertThat(result.currencyCheck?.isAccountFunded).isTrue()
|
||||
coVerify {
|
||||
getCurrencyCheckUseCase(
|
||||
userWalletId = any(),
|
||||
currencyStatus = any(),
|
||||
feeCurrencyStatus = any(),
|
||||
amount = any(),
|
||||
fee = any(),
|
||||
feeCurrencyBalanceAfterTransaction = any(),
|
||||
recipientAddress = DESTINATION_ADDRESS,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region loadFee
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ sealed class SwapEvents(
|
|||
fromCurrency: CryptoCurrency?,
|
||||
toCurrency: CryptoCurrency?,
|
||||
feeNetwork: Network,
|
||||
isTangemPay: Boolean,
|
||||
) : SwapEvents(
|
||||
event = "Transfer in Progress Screen Opened",
|
||||
params = mapOf(
|
||||
|
|
@ -340,6 +341,7 @@ sealed class SwapEvents(
|
|||
RECEIVE_TOKEN to toCurrency?.symbol.orEmpty(),
|
||||
"Receive Blockchain" to toCurrency?.network?.name.orEmpty(),
|
||||
"Network fee" to feeNetwork.name,
|
||||
"Pay Account" to isTangemPay.toString(),
|
||||
),
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
|
|
|
|||
|
|
@ -1491,7 +1491,7 @@ internal class SwapModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun updateTransferModeTangemPayState() {
|
||||
sendTransferInProgressEvent()
|
||||
sendTransferInProgressEvent(isTangemPay = true)
|
||||
uiState = swapTransferStateBuilder.createTangemPayWithdrawalSuccessState(
|
||||
uiState = uiState,
|
||||
dataState = dataState,
|
||||
|
|
@ -1541,7 +1541,7 @@ internal class SwapModel @Inject constructor(
|
|||
""
|
||||
}
|
||||
updateWalletBalance()
|
||||
sendTransferInProgressEvent()
|
||||
sendTransferInProgressEvent(isTangemPay = false)
|
||||
uiState = swapTransferStateBuilder.createSuccessState(
|
||||
uiState = uiState,
|
||||
dataState = dataState,
|
||||
|
|
@ -1564,7 +1564,7 @@ internal class SwapModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun sendTransferInProgressEvent() {
|
||||
private fun sendTransferInProgressEvent(isTangemPay: Boolean) {
|
||||
val fromSwapCurrencyStatus = dataState.fromSwapCurrencyStatus
|
||||
val toSwapCurrencyStatus = dataState.toSwapCurrencyStatus
|
||||
analyticsEventHandler.send(
|
||||
|
|
@ -1572,6 +1572,7 @@ internal class SwapModel @Inject constructor(
|
|||
fromCurrency = fromSwapCurrencyStatus?.currency,
|
||||
toCurrency = toSwapCurrencyStatus?.currency,
|
||||
feeNetwork = getFeeToken().network,
|
||||
isTangemPay = isTangemPay,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ internal class SwapNotificationsFactory(
|
|||
cryptoCurrency = swapCurrencyStatus.currency,
|
||||
feeCryptoCurrency = feeCryptoCurrencyStatus?.currency,
|
||||
isAccountFunded = true, // consider the account is funded on the provider side
|
||||
hasRequiredTrustline = false,
|
||||
)
|
||||
addReduceAmountNotification(
|
||||
cryptoCurrencyStatus = swapCurrencyStatus.status,
|
||||
|
|
|
|||
|
|
@ -126,7 +126,8 @@ internal class SwapTransferNotificationsFactory @Inject constructor() {
|
|||
sendingAmount = amount.value,
|
||||
cryptoCurrency = swapCurrencyStatus.currency,
|
||||
feeCryptoCurrency = feeCryptoCurrencyStatus?.currency,
|
||||
isAccountFunded = true,
|
||||
isAccountFunded = state.currencyCheck?.isAccountFunded == true,
|
||||
hasRequiredTrustline = state.hasRequiredTrustline,
|
||||
)
|
||||
addReduceAmountNotification(
|
||||
cryptoCurrencyStatus = swapCurrencyStatus.status,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue