Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-29 21:24:41 +05:00
parent 9e3a352ff6
commit 8b69fb70dc
10 changed files with 56 additions and 25 deletions

View file

@ -30,13 +30,13 @@ interface SwapTransferInteractor {
suspend fun loadFee(
fromSwapCurrencyStatus: SwapCurrencyStatus,
toSwapCurrencyStatus: SwapCurrencyStatus,
fromTokenAmount: String,
fromTokenAmount: BigDecimal,
): Either<GetFeeError, TransactionFee>
suspend fun loadFeeExtended(
fromSwapCurrencyStatus: SwapCurrencyStatus,
toSwapCurrencyStatus: SwapCurrencyStatus,
fromTokenAmount: String,
fromTokenAmount: BigDecimal,
): Either<GetFeeError, TransactionFeeExtended>
suspend fun sendTransfer(

View file

@ -205,15 +205,14 @@ class SwapTransferInteractorImpl @Inject constructor(
override suspend fun loadFee(
fromSwapCurrencyStatus: SwapCurrencyStatus,
toSwapCurrencyStatus: SwapCurrencyStatus,
fromTokenAmount: String,
fromTokenAmount: BigDecimal,
): Either<GetFeeError, TransactionFee> {
val amount = fromTokenAmount.parseBigDecimalOrNull() ?: BigDecimal.ZERO
val destination = toSwapCurrencyStatus.destinationAddress() ?: return feeDataError(
message = "Destination address is null",
)
return getFeeUseCase(
amount = amount,
amount = fromTokenAmount,
destination = destination,
userWallet = fromSwapCurrencyStatus.userWallet,
cryptoCurrency = fromSwapCurrencyStatus.currency,
@ -223,9 +222,8 @@ class SwapTransferInteractorImpl @Inject constructor(
override suspend fun loadFeeExtended(
fromSwapCurrencyStatus: SwapCurrencyStatus,
toSwapCurrencyStatus: SwapCurrencyStatus,
fromTokenAmount: String,
fromTokenAmount: BigDecimal,
): Either<GetFeeError, TransactionFeeExtended> {
val amount = fromTokenAmount.parseBigDecimalOrNull() ?: BigDecimal.ZERO
val destination = toSwapCurrencyStatus.destinationAddress() ?: return feeDataError(
message = "Destination address is null",
)
@ -233,7 +231,7 @@ class SwapTransferInteractorImpl @Inject constructor(
val currency = fromSwapCurrencyStatus.currency
val transactionData = createTransferTransactionUseCase(
amount = amount.convertToSdkAmount(
amount = fromTokenAmount.convertToSdkAmount(
cryptoCurrencyStatus = fromSwapCurrencyStatus.status,
),
memo = null,

View file

@ -133,7 +133,17 @@ internal class SwapTransferInteractorImplTest {
every { getBalanceHidingSettingsUseCase.isBalanceHidden() } returns flowOf(true)
coEvery { isAccountsModeEnabledUseCase.invokeSync() } returns true
val currencyCheck = buildCurrencyCheck()
coEvery { getCurrencyCheckUseCase(any(), any(), any(), any(), any(), any(), any()) } returns currencyCheck
coEvery {
getCurrencyCheckUseCase(
userWalletId = any(),
currencyStatus = any(),
feeCurrencyStatus = any(),
amount = any(),
fee = any(),
feeCurrencyBalanceAfterTransaction = any(),
recipientAddress = any(),
)
} returns currencyCheck
coEvery {
isAmountSubtractAvailableUseCase(any(), any(), any())
} returns false.right()
@ -193,7 +203,17 @@ internal class SwapTransferInteractorImplTest {
every { getBalanceHidingSettingsUseCase.isBalanceHidden() } returns flowOf(true)
coEvery { isAccountsModeEnabledUseCase.invokeSync() } returns true
val currencyCheck = buildCurrencyCheck()
coEvery { getCurrencyCheckUseCase(any(), any(), any(), any(), any(), any(), any()) } returns currencyCheck
coEvery {
getCurrencyCheckUseCase(
userWalletId = any(),
currencyStatus = any(),
feeCurrencyStatus = any(),
amount = any(),
fee = any(),
feeCurrencyBalanceAfterTransaction = any(),
recipientAddress = any(),
)
} returns currencyCheck
coEvery {
isAmountSubtractAvailableUseCase(any(), any(), any())
} returns false.right()
@ -259,7 +279,15 @@ internal class SwapTransferInteractorImplTest {
every { getBalanceHidingSettingsUseCase.isBalanceHidden() } returns flowOf(false)
coEvery { isAccountsModeEnabledUseCase.invokeSync() } returns false
coEvery {
getCurrencyCheckUseCase(any(), any(), any(), any(), any(), any(), any())
getCurrencyCheckUseCase(
userWalletId = any(),
currencyStatus = any(),
feeCurrencyStatus = any(),
amount = any(),
fee = any(),
feeCurrencyBalanceAfterTransaction = any(),
recipientAddress = any(),
)
} returns buildCurrencyCheck()
coEvery {
isAmountSubtractAvailableUseCase(any(), any(), any())
@ -309,7 +337,7 @@ internal class SwapTransferInteractorImplTest {
val result = sut.loadFee(
fromSwapCurrencyStatus = fromCurrencyStatus,
toSwapCurrencyStatus = toCurrencyStatus,
fromTokenAmount = "1.5",
fromTokenAmount = BigDecimal("1.5"),
)
assertThat(result).isEqualTo(transactionFee.right())
@ -365,7 +393,7 @@ internal class SwapTransferInteractorImplTest {
val result = sut.loadFeeExtended(
fromSwapCurrencyStatus = fromCurrencyStatus,
toSwapCurrencyStatus = toCurrencyStatus,
fromTokenAmount = "2.0",
fromTokenAmount = BigDecimal("2.0"),
)
assertThat(result).isEqualTo(feeExtended.right())

View file

@ -18,7 +18,7 @@ internal class DefaultSwapFeatureToggles @Inject constructor(
)
override val isSwapIntegratedApproveEnabled: Boolean = featureTogglesManager.isFeatureEnabled(
toggle = FeatureToggles.SWAP_INTEGRATED_APPROVE,
toggle = FeatureToggles.AND_15120_SWAP_INTEGRATED_APPROVE,
)
override val isSwapAbEnabled: Boolean = featureTogglesManager.isFeatureEnabled(

View file

@ -2180,6 +2180,7 @@ internal class SwapModel @Inject constructor(
dataState.fromSwapCurrencyStatus ?: return Either.Left(GetFeeError.UnknownError)
val toSwapCurrencyStatus =
dataState.toSwapCurrencyStatus ?: return Either.Left(GetFeeError.UnknownError)
val amount = lastAmount.value.parseBigDecimalOrNull() ?: return Either.Left(GetFeeError.UnknownError)
val shouldTransferInsteadOfSwap = swapTransferInteractor.shouldTransferInsteadOfSwap(
fromSwapCurrencyStatus.currency,
toSwapCurrencyStatus.currency,
@ -2188,7 +2189,7 @@ internal class SwapModel @Inject constructor(
return swapTransferInteractor.loadFee(
fromSwapCurrencyStatus = fromSwapCurrencyStatus,
toSwapCurrencyStatus = toSwapCurrencyStatus,
fromTokenAmount = lastAmount.value,
fromTokenAmount = amount,
).onLeft {
TangemLogger.e("loadFee[transfer]: Failed to load fee with error $it")
}.onRight {
@ -2202,9 +2203,7 @@ internal class SwapModel @Inject constructor(
return Either.Left(GetFeeError.UnknownError)
}
val amountDecimal = lastAmount.value.replace(",", ".").toBigDecimalOrNull()
?: return Either.Left(GetFeeError.UnknownError)
val swapAmount = SwapAmount(amountDecimal, fromSwapCurrencyStatus.currency.decimals)
val swapAmount = SwapAmount(amount, fromSwapCurrencyStatus.currency.decimals)
val swapDataForCall = when (quoteState.swapProvider.type) {
ExchangeProviderType.DEX, ExchangeProviderType.DEX_BRIDGE -> {
quoteState.swapDataModel ?: return Either.Left(GetFeeError.UnknownError)
@ -2235,6 +2234,8 @@ internal class SwapModel @Inject constructor(
dataState.fromSwapCurrencyStatus ?: return Either.Left(GetFeeError.UnknownError)
val toSwapCurrencyStatus =
dataState.toSwapCurrencyStatus ?: return Either.Left(GetFeeError.UnknownError)
val amount = lastAmount.value.parseBigDecimalOrNull() ?: return Either.Left(GetFeeError.UnknownError)
val shouldTransferInsteadOfSwap = swapTransferInteractor.shouldTransferInsteadOfSwap(
fromSwapCurrencyStatus.currency,
toSwapCurrencyStatus.currency,
@ -2243,7 +2244,7 @@ internal class SwapModel @Inject constructor(
return swapTransferInteractor.loadFeeExtended(
fromSwapCurrencyStatus = fromSwapCurrencyStatus,
toSwapCurrencyStatus = toSwapCurrencyStatus,
fromTokenAmount = lastAmount.value,
fromTokenAmount = amount,
)
}
val quoteState = dataState.getCurrentLoadedSwapState() ?: return Either.Left(GetFeeError.UnknownError)
@ -2252,8 +2253,7 @@ internal class SwapModel @Inject constructor(
return Either.Left(GetFeeError.UnknownError)
}
val amountDecimal = lastAmount.value.parseBigDecimalOrNull() ?: return Either.Left(GetFeeError.UnknownError)
val swapAmount = SwapAmount(amountDecimal, fromSwapCurrencyStatus.currency.decimals)
val swapAmount = SwapAmount(amount, fromSwapCurrencyStatus.currency.decimals)
// DEX path requires a SwapDataModel.
val swapDataForCall = when (quoteState.swapProvider.type) {