From 4be3782a0ac50edfb2d4dc91375de9c15076405b Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 30 Oct 2025 17:01:38 +0500 Subject: [PATCH] Updated on 2026-08-14 --- features/swap/data/build.gradle.kts | 1 + .../swap/DefaultSwapTransactionRepository.kt | 27 +++++++++- .../SavedSwapTransactionListConverter.kt | 52 ++++++++++++++++--- .../tangem/feature/swap/di/SwapDataModule.kt | 6 +++ .../domain/SavedSwapTransactionListModel.kt | 3 ++ .../feature/swap/domain/SwapInteractor.kt | 2 + .../feature/swap/domain/SwapInteractorImpl.kt | 28 ++++++++++ .../swap/domain/SwapTransactionRepository.kt | 4 ++ .../tangem/feature/swap/model/SwapModel.kt | 2 + 9 files changed, 117 insertions(+), 8 deletions(-) diff --git a/features/swap/data/build.gradle.kts b/features/swap/data/build.gradle.kts index 5a76552289..046da4aa6a 100644 --- a/features/swap/data/build.gradle.kts +++ b/features/swap/data/build.gradle.kts @@ -43,6 +43,7 @@ dependencies { implementation(projects.domain.wallets.models) implementation(projects.domain.transaction.models) implementation(projects.domain.express.models) + implementation(projects.domain.account.status) /** Data */ implementation(projects.data.common) diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt index 67bcaffe1e..ab4f58a5df 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt @@ -8,6 +8,10 @@ import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.getObjectList import com.tangem.datasource.local.preferences.utils.getObjectListSync import com.tangem.datasource.local.preferences.utils.getObjectMap +import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles +import com.tangem.domain.account.producer.SingleAccountListProducer +import com.tangem.domain.account.supplier.SingleAccountListSupplier +import com.tangem.domain.models.account.Account import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWallet @@ -19,11 +23,14 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.addOrReplace import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn internal class DefaultSwapTransactionRepository( private val appPreferencesStore: AppPreferencesStore, private val dispatchers: CoroutineDispatcherProvider, + private val singleAccountListSupplier: SingleAccountListSupplier, + private val accountsFeatureToggles: AccountsFeatureToggles, responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory, networkFactory: NetworkFactory, ) : SwapTransactionRepository { @@ -40,6 +47,8 @@ internal class DefaultSwapTransactionRepository( userWalletId: UserWalletId, fromCryptoCurrency: CryptoCurrency, toCryptoCurrency: CryptoCurrency, + fromAccount: Account.CryptoPortfolio?, + toAccount: Account.CryptoPortfolio?, transaction: SavedSwapTransactionModel, ) { transaction.status?.let { @@ -73,12 +82,16 @@ internal class DefaultSwapTransactionRepository( userWalletId = userWalletId, fromCryptoCurrency = fromCryptoCurrency, toCryptoCurrency = toCryptoCurrency, + fromAccount = fromAccount, + toAccount = toAccount, transactions = tokenTransactions, ) ?: listOf( converter.default( userWalletId = userWalletId, fromCryptoCurrency = fromCryptoCurrency, toCryptoCurrency = toCryptoCurrency, + fromAccount = fromAccount, + toAccount = toAccount, tokenTransactions = listOf(transaction), ), ), @@ -97,7 +110,12 @@ internal class DefaultSwapTransactionRepository( flow2 = appPreferencesStore.getObjectMap( key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY, ), - ) { savedTransactions, txStatuses -> + flow3 = if (accountsFeatureToggles.isFeatureEnabled) { + singleAccountListSupplier(SingleAccountListProducer.Params(userWallet.walletId)) + } else { + flowOf(null) + }, + ) { savedTransactions, txStatuses, accountList -> val currencyToTxs = savedTransactions?.filter { val isUserWallet = it.userWalletId == userWallet.walletId.stringValue @@ -115,6 +133,7 @@ internal class DefaultSwapTransactionRepository( converter.convertBack( value = it, userWallet = userWallet, + accountList = accountList, txStatuses = txStatuses, onFilter = { it.swapTxTypeDTO == SwapTxTypeDTO.Swap }, ) @@ -124,6 +143,7 @@ internal class DefaultSwapTransactionRepository( converter.convertBack( value = it, userWallet = userWallet, + accountList = accountList, txStatuses = txStatuses, ) }.orEmpty() @@ -223,10 +243,13 @@ internal class DefaultSwapTransactionRepository( fromCryptoCurrencyId == fromCurrencyId.value } + @Suppress("LongParameterList") private fun List.updateList( userWalletId: UserWalletId, fromCryptoCurrency: CryptoCurrency, toCryptoCurrency: CryptoCurrency, + fromAccount: Account.CryptoPortfolio?, + toAccount: Account.CryptoPortfolio?, transactions: List, ): List { return addOrReplace( @@ -234,6 +257,8 @@ internal class DefaultSwapTransactionRepository( userWalletId = userWalletId, fromCryptoCurrency = fromCryptoCurrency, toCryptoCurrency = toCryptoCurrency, + fromAccount = fromAccount, + toAccount = toAccount, tokenTransactions = transactions, ), predicate = { diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt index 261e5f675c..3144aa0a95 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt @@ -6,6 +6,9 @@ import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory import com.tangem.data.common.currency.UserTokensResponseFactory import com.tangem.data.common.network.NetworkFactory import com.tangem.datasource.api.tangemTech.models.UserTokensResponse +import com.tangem.domain.account.models.AccountList +import com.tangem.domain.models.account.Account +import com.tangem.domain.models.account.DerivationIndex import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWallet @@ -29,33 +32,37 @@ internal class SavedSwapTransactionListConverter( toCryptoCurrencyId = value.toCryptoCurrencyId, fromTokensResponse = userTokensResponseFactory.createResponseToken( currency = value.fromCryptoCurrency, - accountId = null, + accountId = value.fromAccount?.accountId, ), toTokensResponse = userTokensResponseFactory.createResponseToken( currency = value.toCryptoCurrency, - accountId = null, + accountId = value.toAccount?.accountId, ), transactions = value.transactions, ) fun convertBack( value: SavedSwapTransactionListModelInner, + accountList: AccountList?, userWallet: UserWallet, txStatuses: Map, onFilter: (SavedSwapTransactionModel) -> Boolean = { true }, ): SavedSwapTransactionListModel? { val fromToken = value.fromTokensResponse val toToken = value.toTokensResponse + val fromDerivationIndex = fromToken?.getDerivationIndex() + val toDerivationIndex = toToken?.getDerivationIndex() + return if (fromToken == null || toToken == null) { null } else { - val fromNetwork = createSwapTransactionNetwork(fromToken, userWallet) ?: return null + val fromNetwork = createSwapTransactionNetwork(fromToken, userWallet, fromDerivationIndex) ?: return null val fromCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency( responseToken = fromToken, userWallet = userWallet, network = fromNetwork, ) ?: return null - val toNetwork = createSwapTransactionNetwork(fromToken, userWallet) ?: return null + val toNetwork = createSwapTransactionNetwork(toToken, userWallet, toDerivationIndex) ?: return null val toCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency( responseToken = toToken, userWallet = userWallet, @@ -81,14 +88,25 @@ internal class SavedSwapTransactionListConverter( toCryptoCurrencyId = value.toCryptoCurrencyId, fromCryptoCurrency = fromCryptoCurrency, toCryptoCurrency = toCryptoCurrency, + fromAccount = findAccountByDerivationIndex( + accountList = accountList, + derivationIndex = fromDerivationIndex, + ), + toAccount = findAccountByDerivationIndex( + accountList = accountList, + derivationIndex = toDerivationIndex, + ), ) } } + @Suppress("LongParameterList") fun default( userWalletId: UserWalletId, fromCryptoCurrency: CryptoCurrency, toCryptoCurrency: CryptoCurrency, + fromAccount: Account.CryptoPortfolio?, + toAccount: Account.CryptoPortfolio?, tokenTransactions: List, ) = SavedSwapTransactionListModelInner( userWalletId = userWalletId.stringValue, @@ -96,13 +114,20 @@ internal class SavedSwapTransactionListConverter( toCryptoCurrencyId = toCryptoCurrency.id.value, fromTokensResponse = userTokensResponseFactory.createResponseToken( currency = fromCryptoCurrency, - accountId = null, + accountId = fromAccount?.accountId, + ), + toTokensResponse = userTokensResponseFactory.createResponseToken( + currency = toCryptoCurrency, + accountId = toAccount?.accountId, ), - toTokensResponse = userTokensResponseFactory.createResponseToken(currency = toCryptoCurrency, accountId = null), transactions = tokenTransactions, ) - private fun createSwapTransactionNetwork(token: UserTokensResponse.Token, userWallet: UserWallet): Network? { + private fun createSwapTransactionNetwork( + token: UserTokensResponse.Token, + userWallet: UserWallet, + accountIndex: DerivationIndex?, + ): Network? { val blockchain = Blockchain.fromNetworkId(token.networkId) ?: return null return if (token.derivationPath == null) { @@ -116,7 +141,20 @@ internal class SavedSwapTransactionListConverter( blockchain = blockchain, extraDerivationPath = token.derivationPath, userWallet = userWallet, + accountIndex = accountIndex, ) } } + + private fun findAccountByDerivationIndex( + accountList: AccountList?, + derivationIndex: DerivationIndex?, + ): Account.CryptoPortfolio? { + return accountList?.accounts?.asSequence()?.filterIsInstance() + ?.firstOrNull { it.derivationIndex == derivationIndex } + } + + private fun UserTokensResponse.Token.getDerivationIndex(): DerivationIndex? { + return accountId?.toIntOrNull()?.let { DerivationIndex(it).getOrNull() } + } } \ No newline at end of file diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt index b80b472729..bb9b016c41 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt @@ -10,6 +10,8 @@ import com.tangem.datasource.crypto.DataSignatureVerifier import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.userwallet.UserWalletsStore +import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles +import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.exchange.RampStateManager import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.feature.swap.DefaultSwapRepository @@ -62,12 +64,16 @@ internal class SwapDataModule { appPreferencesStore: AppPreferencesStore, responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory, networkFactory: NetworkFactory, + singleAccountListSupplier: SingleAccountListSupplier, + accountsFeatureToggles: AccountsFeatureToggles, dispatcherProvider: CoroutineDispatcherProvider, ): SwapTransactionRepository { return DefaultSwapTransactionRepository( appPreferencesStore = appPreferencesStore, responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory, networkFactory = networkFactory, + singleAccountListSupplier = singleAccountListSupplier, + accountsFeatureToggles = accountsFeatureToggles, dispatchers = dispatcherProvider, ) } diff --git a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/SavedSwapTransactionListModel.kt b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/SavedSwapTransactionListModel.kt index 94742cbac9..f25e4b1c1a 100644 --- a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/SavedSwapTransactionListModel.kt +++ b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/SavedSwapTransactionListModel.kt @@ -3,6 +3,7 @@ package com.tangem.feature.swap.domain.models.domain import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import com.tangem.datasource.api.tangemTech.models.UserTokensResponse +import com.tangem.domain.models.account.Account import com.tangem.domain.models.currency.CryptoCurrency import java.math.BigDecimal @@ -12,6 +13,8 @@ data class SavedSwapTransactionListModel( val toCryptoCurrencyId: String, val fromCryptoCurrency: CryptoCurrency, val toCryptoCurrency: CryptoCurrency, + val fromAccount: Account.CryptoPortfolio?, + val toAccount: Account.CryptoPortfolio?, val transactions: List, ) 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 73d1b16834..09dbef0286 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 @@ -71,6 +71,8 @@ interface SwapInteractor { swapData: SwapDataModel?, currencyToSend: CryptoCurrencyStatus, currencyToGet: CryptoCurrencyStatus, + fromAccount: Account.CryptoPortfolio?, + toAccount: Account.CryptoPortfolio?, amountToSwap: String, includeFeeInAmount: IncludeFeeInAmount, fee: TxFee, 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 3310348e4f..cab225f602 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 @@ -714,6 +714,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( swapData: SwapDataModel?, currencyToSend: CryptoCurrencyStatus, currencyToGet: CryptoCurrencyStatus, + fromAccount: Account.CryptoPortfolio?, + toAccount: Account.CryptoPortfolio?, amountToSwap: String, includeFeeInAmount: IncludeFeeInAmount, fee: TxFee, @@ -749,6 +751,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( onSwapCex( currencyToSend = currencyToSend, currencyToGet = currencyToGet, + fromAccount = fromAccount, + toAccount = toAccount, amount = amountToSwapWithFee, txFee = fee, swapProvider = swapProvider, @@ -764,6 +768,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( swapData = requireNotNull(swapData), currencyToSendStatus = currencyToSend, currencyToGetStatus = currencyToGet, + fromAccount = fromAccount, + toAccount = toAccount, amountToSwap = amountToSwap, ) } else { @@ -773,6 +779,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( swapData = requireNotNull(swapData), currencyToSendStatus = currencyToSend, currencyToGetStatus = currencyToGet, + fromAccount = fromAccount, + toAccount = toAccount, txFee = fee, amountToSwap = amountToSwap, ) @@ -828,6 +836,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( swapData: SwapDataModel, currencyToSendStatus: CryptoCurrencyStatus, currencyToGetStatus: CryptoCurrencyStatus, + fromAccount: Account.CryptoPortfolio?, + toAccount: Account.CryptoPortfolio?, amountToSwap: String, txFee: TxFee, ): SwapTransactionState { @@ -856,6 +866,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( swapData = swapData, currencyToSendStatus = currencyToSendStatus, currencyToGetStatus = currencyToGetStatus, + fromAccount = fromAccount, + toAccount = toAccount, amount = amount, derivationPath = derivationPath, txData = txData, @@ -869,6 +881,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( swapData: SwapDataModel, currencyToSendStatus: CryptoCurrencyStatus, currencyToGetStatus: CryptoCurrencyStatus, + fromAccount: Account.CryptoPortfolio?, + toAccount: Account.CryptoPortfolio?, amountToSwap: String, ): SwapTransactionState { val dexTransaction = swapData.transaction as? ExpressTransactionModel.DEX @@ -885,6 +899,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( swapData = swapData, currencyToSendStatus = currencyToSendStatus, currencyToGetStatus = currencyToGetStatus, + fromAccount = fromAccount, + toAccount = toAccount, amount = amount, derivationPath = derivationPath, txData = compiledTransaction, @@ -898,6 +914,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( swapData: SwapDataModel, currencyToSendStatus: CryptoCurrencyStatus, currencyToGetStatus: CryptoCurrencyStatus, + fromAccount: Account.CryptoPortfolio?, + toAccount: Account.CryptoPortfolio?, amount: SwapAmount, derivationPath: String?, txData: TransactionData, @@ -924,6 +942,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( storeSwapTransaction( currencyToSend = currencyToSendStatus, currencyToGet = currencyToGetStatus, + fromAccount = fromAccount, + toAccount = toAccount, amount = amount, swapProvider = provider, swapDataModel = swapData, @@ -962,6 +982,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( private suspend fun onSwapCex( currencyToSend: CryptoCurrencyStatus, currencyToGet: CryptoCurrencyStatus, + fromAccount: Account.CryptoPortfolio?, + toAccount: Account.CryptoPortfolio?, amount: SwapAmount, txFee: TxFee, swapProvider: SwapProvider, @@ -1033,6 +1055,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( storeSwapTransaction( currencyToSend = currencyToSend, currencyToGet = currencyToGet, + fromAccount = fromAccount, + toAccount = toAccount, amount = amount, swapProvider = swapProvider, swapDataModel = exchangeData, @@ -1066,6 +1090,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( private suspend fun storeSwapTransaction( currencyToSend: CryptoCurrencyStatus, currencyToGet: CryptoCurrencyStatus, + fromAccount: Account.CryptoPortfolio?, + toAccount: Account.CryptoPortfolio?, amount: SwapAmount, swapProvider: SwapProvider, swapDataModel: SwapDataModel, @@ -1078,6 +1104,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( userWalletId = userWalletId, fromCryptoCurrency = currencyToSend.currency, toCryptoCurrency = currencyToGet.currency, + fromAccount = fromAccount, + toAccount = toAccount, transaction = SavedSwapTransactionModel( txId = swapDataModel.transaction.txId, provider = swapProvider, diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapTransactionRepository.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapTransactionRepository.kt index ef64270e26..122d227590 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapTransactionRepository.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapTransactionRepository.kt @@ -1,5 +1,6 @@ package com.tangem.feature.swap.domain +import com.tangem.domain.models.account.Account import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWallet @@ -11,10 +12,13 @@ import kotlinx.coroutines.flow.Flow interface SwapTransactionRepository { + @Suppress("LongParameterList") suspend fun storeTransaction( userWalletId: UserWalletId, fromCryptoCurrency: CryptoCurrency, toCryptoCurrency: CryptoCurrency, + fromAccount: Account.CryptoPortfolio?, + toAccount: Account.CryptoPortfolio?, transaction: SavedSwapTransactionModel, ) 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 1fd58317e8..ce0227385f 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 @@ -714,6 +714,8 @@ internal class SwapModel @Inject constructor( currencyToSend = fromCurrency, currencyToGet = requireNotNull(dataState.toCryptoCurrency), amountToSwap = requireNotNull(dataState.amount), + fromAccount = dataState.fromAccount, + toAccount = dataState.toAccount, includeFeeInAmount = lastLoadedQuotesState.preparedSwapConfigState.includeFeeInAmount, fee = fee, expressOperationType = ExpressOperationType.SWAP,