Updated on 2026-08-14
This commit is contained in:
parent
9d2f4ffd64
commit
9b0305efe9
2 changed files with 69 additions and 15 deletions
|
|
@ -297,7 +297,6 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
|
||||
val fromTokenAddress = getTokenAddress(fromSwapCurrencyStatus.currency)
|
||||
|
||||
// TODO CHECK YIELD APPROVE
|
||||
val isYieldSwap = fromSwapCurrencyStatus.isYieldSwapActive &&
|
||||
fromSwapCurrencyStatus.currency is CryptoCurrency.Token
|
||||
|
||||
|
|
@ -310,6 +309,8 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
maybeQuote.getOrNull()?.allowanceContract
|
||||
}
|
||||
|
||||
val dexRouterSpenderAddress = maybeQuote.getOrNull()?.allowanceContract
|
||||
|
||||
val allowanceInfo = spenderAddress?.let { allowanceContract ->
|
||||
getAllowanceInfoUseCase(
|
||||
userWalletId = fromSwapCurrencyStatus.userWalletId,
|
||||
|
|
@ -353,6 +354,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
expressOperationType = expressOperationType,
|
||||
allowanceInfo = allowanceInfo,
|
||||
spenderAddress = spenderAddress,
|
||||
dexRouterSpenderAddress = dexRouterSpenderAddress,
|
||||
)
|
||||
} else {
|
||||
val quoteBalanceStatus = if (isBalanceWithoutFeeEnough) {
|
||||
|
|
@ -417,6 +419,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
expressOperationType = expressOperationType,
|
||||
allowanceInfo = null,
|
||||
spenderAddress = null,
|
||||
dexRouterSpenderAddress = null,
|
||||
)
|
||||
} else {
|
||||
provider to getQuotesState(
|
||||
|
|
@ -1621,6 +1624,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
expressOperationType: ExpressOperationType,
|
||||
allowanceInfo: AllowanceInfo?,
|
||||
spenderAddress: String?,
|
||||
dexRouterSpenderAddress: String?,
|
||||
): SwapState {
|
||||
val fromNetworkAddress = fromSwapCurrencyStatus.status.value.networkAddress
|
||||
val dexFromAddress = fromNetworkAddress?.defaultAddress?.value.orEmpty()
|
||||
|
|
@ -1643,8 +1647,8 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
expressOperationType = expressOperationType,
|
||||
).map { swapData ->
|
||||
val dexTx = swapData.transaction as? ExpressTransactionModel.DEX
|
||||
if (dexTx != null && spenderAddress != null && dexTx.allowanceContract == null) {
|
||||
swapData.copy(transaction = dexTx.copy(allowanceContract = spenderAddress))
|
||||
if (dexTx != null && dexRouterSpenderAddress != null && dexTx.allowanceContract == null) {
|
||||
swapData.copy(transaction = dexTx.copy(allowanceContract = dexRouterSpenderAddress))
|
||||
} else {
|
||||
swapData
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then
|
||||
assertThat(result).hasSize(2)
|
||||
|
|
@ -153,7 +153,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "not-a-number",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then
|
||||
assertThat(result).hasSize(1)
|
||||
|
|
@ -174,7 +174,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "1.0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then
|
||||
assertThat(result).isEmpty()
|
||||
|
|
@ -268,7 +268,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "1.0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then
|
||||
assertThat(result).hasSize(1)
|
||||
|
|
@ -315,7 +315,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "1.0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then
|
||||
assertThat(result).hasSize(1)
|
||||
|
|
@ -431,7 +431,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "1.0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then
|
||||
assertThat(result).hasSize(1)
|
||||
|
|
@ -500,7 +500,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "1.0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then
|
||||
assertThat(result).hasSize(1)
|
||||
|
|
@ -622,7 +622,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "1000.0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then
|
||||
assertThat(result).hasSize(1)
|
||||
|
|
@ -668,7 +668,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "1.0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then
|
||||
assertThat(result).hasSize(1)
|
||||
|
|
@ -711,7 +711,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "1.0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then
|
||||
assertThat(result).hasSize(1)
|
||||
|
|
@ -793,7 +793,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "1.0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then — both providers have an entry
|
||||
assertThat(result).hasSize(2)
|
||||
|
|
@ -862,7 +862,7 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
amountToSwap = "1.0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
// Then — all three providers are dispatched and each has an entry
|
||||
assertThat(result).hasSize(3)
|
||||
|
|
@ -939,6 +939,56 @@ internal class SwapInteractorImplFindBestQuoteTest : SwapInteractorImplTestBase(
|
|||
assertThat(loaded.permissionState).isEqualTo(PermissionDataState.Empty)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `yield swap on-chain spender is DEX router from quote, not yield-module proxy`() = runTest {
|
||||
val dexRouter = "0xDexRouterFromQuote"
|
||||
val dexProvider = buildSwapProvider(ExchangeProviderType.DEX)
|
||||
val fromStatus = buildSwapCurrencyStatus(
|
||||
networkRawId = ethNetwork,
|
||||
contractAddress = yieldTokenContract,
|
||||
isCoin = false,
|
||||
amount = BigDecimal("10"),
|
||||
yieldSupplyActive = true,
|
||||
yieldSupplyAllowedToSpend = true,
|
||||
)
|
||||
val toStatus = buildSwapCurrencyStatus(networkRawId = btcNetwork)
|
||||
val quoteModel = buildQuoteModel(allowanceContract = dexRouter)
|
||||
val swapData = buildSwapDataModelDex() // transaction.allowanceContract == null (OKX)
|
||||
|
||||
coEvery {
|
||||
repository.findBestQuote(
|
||||
userWallet = any(), fromContractAddress = any(), fromNetwork = any(),
|
||||
toContractAddress = any(), toNetwork = any(), fromAmount = any(),
|
||||
fromDecimals = any(), toDecimals = any(),
|
||||
providerId = dexProvider.providerId, rateType = any(),
|
||||
)
|
||||
} returns quoteModel.right()
|
||||
coEvery {
|
||||
repository.getExchangeData(
|
||||
userWallet = any(), fromContractAddress = any(), fromNetwork = any(),
|
||||
toContractAddress = any(), fromAddress = any(), toNetwork = any(),
|
||||
fromAmount = any(), fromDecimals = any(), toDecimals = any(),
|
||||
providerId = dexProvider.providerId, rateType = any(), toAddress = any(),
|
||||
expressOperationType = any(), refundAddress = any(),
|
||||
)
|
||||
} returns swapData.right()
|
||||
|
||||
// When
|
||||
val result = sut.findBestQuote(
|
||||
fromSwapCurrencyStatus = fromStatus,
|
||||
toSwapCurrencyStatus = toStatus,
|
||||
providers = listOf(dexProvider),
|
||||
amountToSwap = "1.0",
|
||||
reduceBalanceBy = BigDecimal.ZERO,
|
||||
)
|
||||
|
||||
// Then — swap data spender is the DEX router from the quote, NOT the yield-module proxy
|
||||
val loaded = result[dexProvider] as SwapState.QuotesLoadedState
|
||||
val dexTx = loaded.swapDataModel?.transaction as ExpressTransactionModel.DEX
|
||||
assertThat(dexTx.allowanceContract).isEqualTo(dexRouter)
|
||||
assertThat(dexTx.allowanceContract).isNotEqualTo(yieldProxyAddress)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should request approval to yield-module proxy when isAllowedToSpend is false`() = runTest {
|
||||
// Given — yield active, approve to proxy revoked → flow must surface PermissionRequired
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue