From 042df9828f63eb8155f4caff700a926aeb8801e6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 1 Sep 2025 18:00:10 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../datasource/api/express/TangemExpressApi.kt | 1 + .../com/tangem/data/swap/DefaultSwapRepositoryV2.kt | 3 +++ .../domain/express/models/ExpressOperationType.kt | 6 ++++++ .../java/com/tangem/domain/swap/SwapRepositoryV2.kt | 3 +++ .../tangem/domain/swap/usecase/GetSwapDataUseCase.kt | 3 +++ .../confirm/model/SendWithSwapConfirmModel.kt | 2 ++ .../confirm/model/SwapTransactionSender.kt | 5 +++++ features/swap/data/build.gradle.kts | 1 + .../com/tangem/feature/swap/DefaultSwapRepository.kt | 3 +++ features/swap/domain/api/build.gradle.kts | 1 + .../tangem/feature/swap/domain/api/SwapRepository.kt | 2 ++ features/swap/domain/build.gradle.kts | 1 + .../com/tangem/feature/swap/domain/SwapInteractor.kt | 2 ++ .../tangem/feature/swap/domain/SwapInteractorImpl.kt | 12 +++++++++++- features/swap/impl/build.gradle.kts | 1 + .../java/com/tangem/feature/swap/model/SwapModel.kt | 2 ++ 16 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 domain/express/models/src/main/java/com/tangem/domain/express/models/ExpressOperationType.kt diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt index a57712606b..3a4c3d9e84 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt @@ -66,6 +66,7 @@ interface TangemExpressApi { @Query("requestId") requestId: String, @Query("refundAddress") refundAddress: String?, // for cex only @Query("refundExtraId") refundExtraId: String?, // for cex only + @Query("partnerOperationType") partnerOperationType: String?, // swap/ swap-and-send ): ApiResponse @GET("exchange-status") diff --git a/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapRepositoryV2.kt b/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapRepositoryV2.kt index 82aa29d68a..5f67f6400f 100644 --- a/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapRepositoryV2.kt +++ b/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapRepositoryV2.kt @@ -18,6 +18,7 @@ import com.tangem.datasource.exchangeservice.swap.ExpressUtils import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.domain.express.ExpressRepository import com.tangem.domain.express.models.ExpressError +import com.tangem.domain.express.models.ExpressOperationType import com.tangem.domain.express.models.ExpressProvider import com.tangem.domain.express.models.ExpressProviderType import com.tangem.domain.express.models.ExpressRateType @@ -208,6 +209,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor( toAddress: String, expressProvider: ExpressProvider, rateType: ExpressRateType, + expressOperationType: ExpressOperationType, ): SwapDataModel = withContext(coroutineDispatcher.io) { val requestId = UUID.randomUUID().toString() val fromCryptoCurrency = fromCryptoCurrencyStatus.currency @@ -239,6 +241,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor( refundAddress = refundData?.refundAddress, refundExtraId = refundData?.refundExtraId, userWalletId = userWallet.walletId.stringValue, + partnerOperationType = expressOperationType.value, refCode = ExpressUtils.getRefCode( userWallet = userWallet, appPreferencesStore = appPreferencesStore, diff --git a/domain/express/models/src/main/java/com/tangem/domain/express/models/ExpressOperationType.kt b/domain/express/models/src/main/java/com/tangem/domain/express/models/ExpressOperationType.kt new file mode 100644 index 0000000000..7c836ad588 --- /dev/null +++ b/domain/express/models/src/main/java/com/tangem/domain/express/models/ExpressOperationType.kt @@ -0,0 +1,6 @@ +package com.tangem.domain.express.models + +enum class ExpressOperationType(val value: String) { + SWAP("swap"), + SEND_WITH_SWAP("swap-and-send"), +} \ No newline at end of file diff --git a/domain/swap/src/main/java/com/tangem/domain/swap/SwapRepositoryV2.kt b/domain/swap/src/main/java/com/tangem/domain/swap/SwapRepositoryV2.kt index b94e923f2f..d25708c229 100644 --- a/domain/swap/src/main/java/com/tangem/domain/swap/SwapRepositoryV2.kt +++ b/domain/swap/src/main/java/com/tangem/domain/swap/SwapRepositoryV2.kt @@ -1,5 +1,6 @@ package com.tangem.domain.swap +import com.tangem.domain.express.models.ExpressOperationType import com.tangem.domain.express.models.ExpressProvider import com.tangem.domain.express.models.ExpressProviderType import com.tangem.domain.express.models.ExpressRateType @@ -74,6 +75,7 @@ interface SwapRepositoryV2 { * @param toAddress destination address * @param expressProvider selected swap provider * @param rateType selected provider rate type + * @param expressOperationType operation type swap or send with swap */ suspend fun getSwapData( userWallet: UserWallet, @@ -83,6 +85,7 @@ interface SwapRepositoryV2 { toAddress: String, expressProvider: ExpressProvider, rateType: ExpressRateType, + expressOperationType: ExpressOperationType, ): SwapDataModel /** diff --git a/domain/swap/src/main/java/com/tangem/domain/swap/usecase/GetSwapDataUseCase.kt b/domain/swap/src/main/java/com/tangem/domain/swap/usecase/GetSwapDataUseCase.kt index ac60b660e2..0f0638c9a8 100644 --- a/domain/swap/src/main/java/com/tangem/domain/swap/usecase/GetSwapDataUseCase.kt +++ b/domain/swap/src/main/java/com/tangem/domain/swap/usecase/GetSwapDataUseCase.kt @@ -2,6 +2,7 @@ package com.tangem.domain.swap.usecase import arrow.core.Either import com.tangem.domain.express.models.ExpressError +import com.tangem.domain.express.models.ExpressOperationType import com.tangem.domain.express.models.ExpressProvider import com.tangem.domain.express.models.ExpressRateType import com.tangem.domain.models.currency.CryptoCurrency @@ -25,6 +26,7 @@ class GetSwapDataUseCase( toAddress: String, expressProvider: ExpressProvider, rateType: ExpressRateType, + expressOperationType: ExpressOperationType, ): Either = Either.catch { swapRepositoryV2.getSwapData( userWallet = userWallet, @@ -34,6 +36,7 @@ class GetSwapDataUseCase( toAddress = toAddress, expressProvider = expressProvider, rateType = rateType, + expressOperationType = expressOperationType, ) }.mapLeft { throwable -> swapErrorResolver.resolve(throwable) diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt index cebaaba9dd..a434134267 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt @@ -17,6 +17,7 @@ import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router import com.tangem.core.ui.extensions.resourceReference +import com.tangem.domain.express.models.ExpressOperationType import com.tangem.domain.express.models.ExpressProviderType import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus @@ -293,6 +294,7 @@ internal class SendWithSwapConfirmModel @Inject constructor( } router.replaceAll(SendWithSwapRoute.Success) }, + expressOperationType = ExpressOperationType.SEND_WITH_SWAP, ) } } diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SwapTransactionSender.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SwapTransactionSender.kt index 458d1ebd4e..91239d4afe 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SwapTransactionSender.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SwapTransactionSender.kt @@ -3,6 +3,7 @@ package com.tangem.features.swap.v2.impl.sendviaswap.confirm.model import arrow.core.getOrElse import com.tangem.blockchain.common.transaction.Fee import com.tangem.domain.express.models.ExpressError +import com.tangem.domain.express.models.ExpressOperationType import com.tangem.domain.express.models.ExpressProvider import com.tangem.domain.express.models.ExpressProviderType import com.tangem.domain.models.currency.CryptoCurrencyStatus @@ -40,6 +41,7 @@ internal class SwapTransactionSender @AssistedInject constructor( onSendSuccess: (String, Long, SwapDataModel) -> Unit, onExpressError: (ExpressError) -> Unit, onSendError: (SendTransactionError?) -> Unit, + expressOperationType: ExpressOperationType, ) { val provider = confirmData.quote?.provider ?: return @@ -50,6 +52,7 @@ internal class SwapTransactionSender @AssistedInject constructor( onExpressError = onExpressError, onSendSuccess = onSendSuccess, onSendError = onSendError, + expressOperationType = expressOperationType, ) ExpressProviderType.DEX, ExpressProviderType.DEX_BRIDGE, @@ -67,6 +70,7 @@ internal class SwapTransactionSender @AssistedInject constructor( onSendSuccess: (String, Long, SwapDataModel) -> Unit, onExpressError: (ExpressError) -> Unit, onSendError: (SendTransactionError?) -> Unit, + expressOperationType: ExpressOperationType, ) { val fromStatus = confirmData.fromCryptoCurrencyStatus ?: return val toStatus = confirmData.toCryptoCurrencyStatus ?: return @@ -92,6 +96,7 @@ internal class SwapTransactionSender @AssistedInject constructor( toAddress = destination, expressProvider = provider, rateType = rateType, + expressOperationType, ).getOrElse { onExpressError(it); return } createAndSendCexTransaction( diff --git a/features/swap/data/build.gradle.kts b/features/swap/data/build.gradle.kts index 5b0d422759..5a76552289 100644 --- a/features/swap/data/build.gradle.kts +++ b/features/swap/data/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { implementation(projects.domain.wallets) implementation(projects.domain.wallets.models) implementation(projects.domain.transaction.models) + implementation(projects.domain.express.models) /** Data */ implementation(projects.data.common) diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt index 96a200e419..a05a0f0b26 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt @@ -27,6 +27,7 @@ import com.tangem.datasource.exchangeservice.swap.ExpressUtils import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.exchange.RampStateManager +import com.tangem.domain.express.models.ExpressOperationType import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId @@ -283,6 +284,7 @@ internal class DefaultSwapRepository( providerId: String, rateType: RateType, toAddress: String, + expressOperationType: ExpressOperationType, refundAddress: String?, // for cex only refundExtraId: String?, // for cex only ): Either { @@ -304,6 +306,7 @@ internal class DefaultSwapRepository( requestId = requestId, refundAddress = refundAddress, refundExtraId = refundExtraId, + partnerOperationType = expressOperationType.value, userWalletId = userWallet.walletId.stringValue, refCode = ExpressUtils.getRefCode( userWallet = userWallet, diff --git a/features/swap/domain/api/build.gradle.kts b/features/swap/domain/api/build.gradle.kts index 38ecfe752e..cee9c5f63d 100644 --- a/features/swap/domain/api/build.gradle.kts +++ b/features/swap/domain/api/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { implementation(projects.features.swap.domain.models) implementation(projects.domain.tokens.models) implementation(projects.domain.wallets.models) + implementation(projects.domain.express.models) implementation(deps.arrow.core) diff --git a/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt b/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt index 552ee983aa..7473ad49ae 100644 --- a/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt +++ b/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt @@ -1,6 +1,7 @@ package com.tangem.feature.swap.domain.api import arrow.core.Either +import com.tangem.domain.express.models.ExpressOperationType import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId @@ -64,6 +65,7 @@ interface SwapRepository { providerId: String, rateType: RateType, toAddress: String, + expressOperationType: ExpressOperationType, refundAddress: String? = null, // for cex only refundExtraId: String? = null, // for cex only ): Either diff --git a/features/swap/domain/build.gradle.kts b/features/swap/domain/build.gradle.kts index 256c69cbac..8adde9bd53 100644 --- a/features/swap/domain/build.gradle.kts +++ b/features/swap/domain/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { implementation(projects.domain.txhistory.models) implementation(projects.domain.wallets) implementation(projects.domain.wallets.models) + implementation(projects.domain.express.models) implementation(projects.features.swap.domain.api) implementation(projects.features.swap.domain.models) diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt index 3646a0d6b5..97a8cfc718 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt @@ -1,5 +1,6 @@ package com.tangem.feature.swap.domain +import com.tangem.domain.express.models.ExpressOperationType import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWalletId @@ -65,6 +66,7 @@ interface SwapInteractor { amountToSwap: String, includeFeeInAmount: IncludeFeeInAmount, fee: TxFee, + expressOperationType: ExpressOperationType, ): SwapTransactionState // suspend fun updateQuotesStateWithSelectedFee( diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index de44a22010..1d9a24f713 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -18,6 +18,7 @@ import com.tangem.domain.appcurrency.extenstions.unwrap import com.tangem.domain.appcurrency.repository.AppCurrencyRepository import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.exchange.RampStateManager +import com.tangem.domain.express.models.ExpressOperationType import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.network.Network @@ -288,6 +289,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( selectedFee = selectedFee, amount = amount, isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough, + expressOperationType = ExpressOperationType.SWAP, ) } ExchangeProviderType.CEX -> { @@ -314,6 +316,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( selectedFee: FeeType, amount: SwapAmount, isBalanceWithoutFeeEnough: Boolean, + expressOperationType: ExpressOperationType, ): Pair { val maybeQuotes = repository.findBestQuote( userWallet = userWallet, @@ -350,6 +353,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( toToken = toToken, amount = amount, selectedFee = selectedFee, + expressOperationType = expressOperationType, ) } else { provider to getQuotesState( @@ -496,6 +500,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( amountToSwap: String, includeFeeInAmount: IncludeFeeInAmount, fee: TxFee, + expressOperationType: ExpressOperationType, ): SwapTransactionState { Timber.i( """ @@ -530,6 +535,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( amount = amountToSwapWithFee, txFee = fee, swapProvider = swapProvider, + expressOperationType = expressOperationType, ) } ExchangeProviderType.DEX, ExchangeProviderType.DEX_BRIDGE -> { @@ -677,6 +683,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( amount: SwapAmount, txFee: TxFee, swapProvider: SwapProvider, + expressOperationType: ExpressOperationType, ): SwapTransactionState { val exchangeData = repository.getExchangeData( userWallet = userWallet, @@ -690,9 +697,10 @@ internal class SwapInteractorImpl @AssistedInject constructor( toDecimals = currencyToGet.currency.decimals, providerId = swapProvider.providerId, rateType = RateType.FLOAT, + expressOperationType = expressOperationType, toAddress = currencyToGet.value.networkAddress?.defaultAddress?.value.orEmpty(), refundAddress = currencyToSend.value.networkAddress?.defaultAddress?.value, - refundExtraId = null, // currently always null + refundExtraId = null, // currently always null, ).getOrElse { return SwapTransactionState.Error.ExpressError(it) } val exchangeDataCex = @@ -1162,6 +1170,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( toToken: CryptoCurrencyStatus, amount: SwapAmount, selectedFee: FeeType, + expressOperationType: ExpressOperationType, ): SwapState { return repository.getExchangeData( userWallet = userWallet, @@ -1177,6 +1186,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( rateType = RateType.FLOAT, toAddress = toToken.value.networkAddress?.defaultAddress?.value.orEmpty(), refundAddress = fromToken.value.networkAddress?.defaultAddress?.value, + expressOperationType = expressOperationType, ).fold( ifRight = { swapData -> val transaction = swapData.transaction as ExpressTransactionModel.DEX diff --git a/features/swap/impl/build.gradle.kts b/features/swap/impl/build.gradle.kts index ed1a7f3f50..c87d68c2df 100644 --- a/features/swap/impl/build.gradle.kts +++ b/features/swap/impl/build.gradle.kts @@ -43,6 +43,7 @@ dependencies { implementation(projects.domain.promo.models) implementation(projects.domain.txhistory) implementation(projects.domain.txhistory.models) + implementation(projects.domain.express.models) /** Feature modules */ implementation(projects.features.swap.domain) diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt index 2e8026f8db..b1c067828a 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt @@ -23,6 +23,7 @@ import com.tangem.core.ui.utils.InputNumberFormatter import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase +import com.tangem.domain.express.models.ExpressOperationType import com.tangem.domain.feedback.GetCardInfoUseCase import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase @@ -613,6 +614,7 @@ internal class SwapModel @Inject constructor( amountToSwap = requireNotNull(dataState.amount), includeFeeInAmount = lastLoadedQuotesState.preparedSwapConfigState.includeFeeInAmount, fee = fee, + expressOperationType = ExpressOperationType.SWAP, ) }.onSuccess { when (it) {