diff --git a/detekt_baseline_report.txt b/detekt_baseline_report.txt
index a45e2bff61..d36313f946 100644
--- a/detekt_baseline_report.txt
+++ b/detekt_baseline_report.txt
@@ -1,7 +1,7 @@
==========================================
Detekt Baseline Updater & Issue Counter
==========================================
-Date: 2025-12-12 13:17:20
+Date: 2025-12-13 00:34:09
Step 1: Running detekt to check for new issues...
@@ -17,13 +17,13 @@ Counting issues in baseline files...
==========================================
Summary:
- Total Issues: 1378
- Modules with Issues: 72
- Average Issues per Module: 19
+ Total Issues: 1271
+ Modules with Issues: 69
+ Average Issues per Module: 18
Progress:
- Fixed: 555 out of 1933 (28%)
- Remaining: 1378
+ Fixed: 662 out of 1933 (34%)
+ Remaining: 1271
==========================================
All Modules with Issues (sorted by count)
@@ -34,7 +34,6 @@ Module Issues
features/markets/impl 147
features/wallet/impl 144
features/onboarding-v2/impl 128
-features/swap/impl 67
data/wallet-connect 54
features/hot-wallet/impl 51
features/walletconnect/impl 47
@@ -45,7 +44,6 @@ domain/wallets 37
features/nft/impl 34
features/tester/impl 28
core/ui 26
-features/swap/domain 25
domain/tokens 25
common/ui 24
features/yield-supply/impl 21
@@ -54,7 +52,6 @@ domain/models 21
data/visa 21
data/nft 19
core/pagination 16
-features/swap/data 15
domain/staking/models 13
data/wallets 13
features/token-recieve/impl 11
diff --git a/features/swap/data/detekt-baseline-debug.xml b/features/swap/data/detekt-baseline-debug.xml
deleted file mode 100644
index 640fd2fbc1..0000000000
--- a/features/swap/data/detekt-baseline-debug.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
- BooleanPropertyNaming:DefaultSwapTransactionRepository.kt$DefaultSwapTransactionRepository$val fromCurrency = it.fromCryptoCurrencyId == cryptoCurrencyId.value
- BooleanPropertyNaming:DefaultSwapTransactionRepository.kt$DefaultSwapTransactionRepository$val toCurrency = it.toCryptoCurrencyId == cryptoCurrencyId.value
- MultilineLambdaItParameter:DefaultSwapRepository.kt$DefaultSwapRepository${ Timber.e("getExchangeStatus error: $it") raise(UnknownError(it.message)) }
- MultilineLambdaItParameter:DefaultSwapRepository.kt$DefaultSwapRepository${ val requirements = walletManagersFacade.getAssetRequirements(userWallet.walletId, it) val isAvailableForSwap = rampStateManager.checkAssetRequirements(requirements) isAvailableForSwap }
- MultilineLambdaItParameter:DefaultSwapTransactionRepository.kt$DefaultSwapTransactionRepository${ converter.convertBack( value = it, userWallet = userWallet, accountList = accountList, txStatuses = txStatuses, ) }
- MultilineLambdaItParameter:DefaultSwapTransactionRepository.kt$DefaultSwapTransactionRepository${ converter.convertBack( value = it, userWallet = userWallet, accountList = accountList, txStatuses = txStatuses, onFilter = { it.swapTxTypeDTO == SwapTxTypeDTO.Swap }, ) }
- MultilineLambdaItParameter:DefaultSwapTransactionRepository.kt$DefaultSwapTransactionRepository${ it.checkId( checkUserWalletId = userWalletId, fromCurrencyId = fromCryptoCurrency.id, toCurrencyId = toCryptoCurrency.id, ) }
- MultilineLambdaItParameter:DefaultSwapTransactionRepository.kt$DefaultSwapTransactionRepository${ storeTransactionState( txId = transaction.txId, status = it, accountWithCurrency = null, ) }
- MultilineLambdaItParameter:DefaultSwapTransactionRepository.kt$DefaultSwapTransactionRepository${ val isUserWallet = it.userWalletId == userWallet.walletId.stringValue val fromCurrency = it.fromCryptoCurrencyId == cryptoCurrencyId.value isUserWallet && fromCurrency }
- MultilineLambdaItParameter:DefaultSwapTransactionRepository.kt$DefaultSwapTransactionRepository${ val isUserWallet = it.userWalletId == userWallet.walletId.stringValue val toCurrency = it.toCryptoCurrencyId == cryptoCurrencyId.value isUserWallet && toCurrency }
- MultilineLambdaItParameter:ExpressDataConverter.kt$ExpressDataConverter${ if (it == "0") { BigDecimal.ZERO } else { requireNotNull(it.toBigDecimalOrNull()) { "wrong amount format, use only digits" } } }
- NoNameShadowing:DefaultSwapTransactionRepository.kt$DefaultSwapTransactionRepository${ it.swapTxTypeDTO == SwapTxTypeDTO.Swap }
- NoNameShadowing:DefaultSwapTransactionRepository.kt$DefaultSwapTransactionRepository${ it.txId == txId }
- UseOrEmpty:DefaultSwapRepository.kt$DefaultSwapRepository$ex.errorBody ?: ""
- UseOrEmpty:DefaultSwapRepository.kt$DefaultSwapRepository$exception.errorBody ?: ""
-
-
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 2f34e89a84..2b464a5d59 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
@@ -118,7 +118,7 @@ internal class DefaultSwapRepository(
)
} catch (exception: Exception) {
if (exception is ApiResponseError.HttpException) {
- throw ExpressException(errorsDataConverter.convert(exception.errorBody ?: ""))
+ throw ExpressException(errorsDataConverter.convert(exception.errorBody.orEmpty()))
} else {
throw exception
}
@@ -138,12 +138,12 @@ internal class DefaultSwapRepository(
network = initialCurrency.network,
)
val currenciesList = currencyList
- .filter {
- val requirements = walletManagersFacade.getAssetRequirements(userWallet.walletId, it)
+ .filter { currency ->
+ val requirements = walletManagersFacade.getAssetRequirements(userWallet.walletId, currency)
val isAvailableForSwap = rampStateManager.checkAssetRequirements(requirements)
isAvailableForSwap
}
- .map { leastTokenInfoConverter.convert(it) }
+ .map { currency -> leastTokenInfoConverter.convert(currency) }
val pairsDeferred = async {
getPairsInternal(
@@ -174,7 +174,7 @@ internal class DefaultSwapRepository(
)
} catch (exception: Exception) {
if (exception is ApiResponseError.HttpException) {
- throw ExpressException(errorsDataConverter.convert(exception.errorBody ?: ""))
+ throw ExpressException(errorsDataConverter.convert(exception.errorBody.orEmpty()))
} else {
throw exception
}
@@ -221,9 +221,9 @@ internal class DefaultSwapRepository(
.getOrThrow(),
)
},
- catch = {
- Timber.e("getExchangeStatus error: $it")
- raise(UnknownError(it.message))
+ catch = { exception ->
+ Timber.e("getExchangeStatus error: $exception")
+ raise(UnknownError(exception.message))
},
)
}
@@ -420,7 +420,7 @@ internal class DefaultSwapRepository(
private fun getDataError(ex: Exception): ExpressDataError {
return if (ex is ApiResponseError.HttpException) {
- errorsDataConverter.convert(ex.errorBody ?: "")
+ errorsDataConverter.convert(ex.errorBody.orEmpty())
} else {
ExpressDataError.UnknownError
}
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 ab4f58a5df..fb7b9d0ed1 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
@@ -51,10 +51,10 @@ internal class DefaultSwapTransactionRepository(
toAccount: Account.CryptoPortfolio?,
transaction: SavedSwapTransactionModel,
) {
- transaction.status?.let {
+ transaction.status?.let { status ->
storeTransactionState(
txId = transaction.txId,
- status = it,
+ status = status,
accountWithCurrency = null,
)
}
@@ -63,8 +63,8 @@ internal class DefaultSwapTransactionRepository(
key = PreferencesKeys.SWAP_TRANSACTIONS_KEY,
)
val tokenTransactions = savedTransactions
- ?.firstOrNull {
- it.checkId(
+ ?.firstOrNull { savedTx ->
+ savedTx.checkId(
checkUserWalletId = userWalletId,
fromCurrencyId = fromCryptoCurrency.id,
toCurrencyId = toCryptoCurrency.id,
@@ -73,7 +73,7 @@ internal class DefaultSwapTransactionRepository(
?.transactions
?.addOrReplace(
item = transaction,
- predicate = { it.txId == transaction.txId },
+ predicate = { tx -> tx.txId == transaction.txId },
) ?: listOf(transaction)
mutablePreferences.setObject(
@@ -117,31 +117,31 @@ internal class DefaultSwapTransactionRepository(
},
) { savedTransactions, txStatuses, accountList ->
- val currencyToTxs = savedTransactions?.filter {
- val isUserWallet = it.userWalletId == userWallet.walletId.stringValue
- val toCurrency = it.toCryptoCurrencyId == cryptoCurrencyId.value
- isUserWallet && toCurrency
+ val currencyToTxs = savedTransactions?.filter { savedTx ->
+ val isUserWallet = savedTx.userWalletId == userWallet.walletId.stringValue
+ val isToCurrency = savedTx.toCryptoCurrencyId == cryptoCurrencyId.value
+ isUserWallet && isToCurrency
}
- val currencyFromTxs = savedTransactions?.filter {
- val isUserWallet = it.userWalletId == userWallet.walletId.stringValue
- val fromCurrency = it.fromCryptoCurrencyId == cryptoCurrencyId.value
- isUserWallet && fromCurrency
+ val currencyFromTxs = savedTransactions?.filter { savedTx ->
+ val isUserWallet = savedTx.userWalletId == userWallet.walletId.stringValue
+ val isFromCurrency = savedTx.fromCryptoCurrencyId == cryptoCurrencyId.value
+ isUserWallet && isFromCurrency
}
- val toTxs = currencyToTxs?.mapNotNull {
+ val toTxs = currencyToTxs?.mapNotNull { savedTx ->
converter.convertBack(
- value = it,
+ value = savedTx,
userWallet = userWallet,
accountList = accountList,
txStatuses = txStatuses,
- onFilter = { it.swapTxTypeDTO == SwapTxTypeDTO.Swap },
+ onFilter = { tx -> tx.swapTxTypeDTO == SwapTxTypeDTO.Swap },
)
}.orEmpty()
- val fromTxs = currencyFromTxs?.mapNotNull {
+ val fromTxs = currencyFromTxs?.mapNotNull { savedTx ->
converter.convertBack(
- value = it,
+ value = savedTx,
userWallet = userWallet,
accountList = accountList,
txStatuses = txStatuses,
@@ -161,9 +161,9 @@ internal class DefaultSwapTransactionRepository(
)
val tokenTransactions = savedList
?.asSequence()
- ?.map {
- it.copy(transactions = it.transactions.filterNot { it.txId == txId })
- }?.filterNot { it.transactions.isEmpty() }
+ ?.map { savedTx ->
+ savedTx.copy(transactions = savedTx.transactions.filterNot { tx -> tx.txId == txId })
+ }?.filterNot { savedTx -> savedTx.transactions.isEmpty() }
?.toList()
if (tokenTransactions.isNullOrEmpty()) {
@@ -261,8 +261,8 @@ internal class DefaultSwapTransactionRepository(
toAccount = toAccount,
tokenTransactions = transactions,
),
- predicate = {
- it.checkId(
+ predicate = { savedTx ->
+ savedTx.checkId(
checkUserWalletId = userWalletId,
fromCurrencyId = fromCryptoCurrency.id,
toCurrencyId = toCryptoCurrency.id,
diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExpressDataConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExpressDataConverter.kt
index 34c663840b..8d605d8dfd 100644
--- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExpressDataConverter.kt
+++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExpressDataConverter.kt
@@ -25,11 +25,11 @@ internal class ExpressDataConverter : Converter
+ if (feeValue == "0") {
BigDecimal.ZERO
} else {
- requireNotNull(it.toBigDecimalOrNull()) { "wrong amount format, use only digits" }
+ requireNotNull(feeValue.toBigDecimalOrNull()) { "wrong amount format, use only digits" }
}
}
ExpressTransactionModel.DEX(
diff --git a/features/swap/domain/detekt-baseline-debug.xml b/features/swap/domain/detekt-baseline-debug.xml
deleted file mode 100644
index e1d3527ea0..0000000000
--- a/features/swap/domain/detekt-baseline-debug.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
- BooleanPropertyNaming:SwapInteractorImpl.kt$SwapInteractorImpl$val allQuotesFound = cachedQuotes?.all { it.value !is QuoteStatus.Empty } == true
- BooleanPropertyNaming:SwapInteractorImpl.kt$SwapInteractorImpl$val currencyFilter = it.currency.network.backendId != currency.network.backendId || it.currency.getContractAddress() != currency.getContractAddress()
- BooleanPropertyNaming:SwapInteractorImpl.kt$SwapInteractorImpl$val notCustomTokenFilter = !it.currency.isCustom
- BooleanPropertyNaming:SwapInteractorImpl.kt$SwapInteractorImpl$val statusFilter = it.value is CryptoCurrencyStatus.Loaded || it.value is CryptoCurrencyStatus.NoAccount
- CanBeNonNullable:SwapInteractorImpl.kt$SwapInteractorImpl$spenderAddress: String?
- MaxChainedCallsOnSameLine:SwapInteractorImpl.kt$SwapInteractorImpl$currencyToGet.value.networkAddress?.defaultAddress?.value.orEmpty()
- MaxChainedCallsOnSameLine:SwapInteractorImpl.kt$SwapInteractorImpl$currencyToSend.value.networkAddress?.defaultAddress?.value.orEmpty()
- MaxChainedCallsOnSameLine:SwapInteractorImpl.kt$SwapInteractorImpl$currencyToSendStatus.value.networkAddress?.defaultAddress?.value.orEmpty()
- MaxChainedCallsOnSameLine:SwapInteractorImpl.kt$SwapInteractorImpl$fromToken.value.networkAddress?.defaultAddress?.value.orEmpty()
- MaxChainedCallsOnSameLine:SwapInteractorImpl.kt$SwapInteractorImpl$toToken.value.networkAddress?.defaultAddress?.value.orEmpty()
- MultilineLambdaItParameter:SwapInteractorImpl.kt$SwapInteractorImpl${ Timber.e(it, "Failed to create approveTransaction") return SwapTransactionState.Error.UnknownError }
- MultilineLambdaItParameter:SwapInteractorImpl.kt$SwapInteractorImpl${ Timber.e(it, "Failed to create swap CEX tx data") return SwapTransactionState.Error.UnknownError }
- MultilineLambdaItParameter:SwapInteractorImpl.kt$SwapInteractorImpl${ Timber.e(it, "Failed to create swap dex tx data") return SwapTransactionState.Error.UnknownError }
- MultilineLambdaItParameter:SwapInteractorImpl.kt$SwapInteractorImpl${ it.contractAddress.equals(feePaidCurrency.contractAddress, ignoreCase = true) && it.network.derivationPath == fromTokenStatus.currency.network.derivationPath }
- MultilineLambdaItParameter:SwapInteractorImpl.kt$SwapInteractorImpl${ tokenInfoForFilter(it).contractAddress == currency.getContractAddress() && tokenInfoForFilter(it).network == currency.network.backendId }
- MultilineLambdaItParameter:SwapInteractorImpl.kt$SwapInteractorImpl${ val currencyFilter = it.currency.network.backendId != currency.network.backendId || it.currency.getContractAddress() != currency.getContractAddress() val statusFilter = it.value is CryptoCurrencyStatus.Loaded || it.value is CryptoCurrencyStatus.NoAccount val notCustomTokenFilter = !it.currency.isCustom statusFilter && currencyFilter && notCustomTokenFilter }
- MultilineLambdaItParameter:SwapInteractorImpl.kt$SwapInteractorImpl${ val listTokenInfo = tokenInfoForAvailable(it) if (cryptoCurrencyStatuses.currency.network.backendId == listTokenInfo.network && cryptoCurrencyStatuses.currency.getContractAddress() == listTokenInfo.contractAddress && isAvailableForSwap ) { it.providers } else { null } }
- NamedArguments:SwapInteractorImpl.kt$SwapInteractorImpl$getCoinBalanceAfterTransaction(fromTokenStatus, amount, includeFeeInAmount, fee)
- NamedArguments:SwapInteractorImpl.kt$SwapInteractorImpl$isAllowedToSpend(networkId, fromToken.currency, amount, it)
- NamedArguments:SwapInteractorImpl.kt$SwapInteractorImpl$tryGetFromCache(userWallet, initialCryptoCurrency, state, isReverseFromTo)
- NamedArguments:SwapInteractorImpl.kt$SwapInteractorImpl$tryGetFromCacheV2(userWallet, initialCryptoCurrency, state, isReverseFromTo)
- NoNameShadowing:SwapInteractorImpl.kt$SwapInteractorImpl$account
- NoNameShadowing:SwapInteractorImpl.kt$SwapInteractorImpl${ it.isAvailable }
- NullableToStringCall:SwapInteractorImpl.kt$SwapInteractorImpl$${e.message}
- SuspendFunSwallowedCancellation:SwapInteractorImpl.kt$SwapInteractorImpl$runCatching
-
-
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 aa8415a3c9..fc9b3e26de 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
@@ -43,6 +43,7 @@ import com.tangem.domain.transaction.error.GetFeeError
import com.tangem.domain.transaction.usecase.*
import com.tangem.domain.utils.convertToSdkAmount
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
+import com.tangem.utils.coroutines.runSuspendCatching
import com.tangem.feature.swap.domain.api.SwapRepository
import com.tangem.feature.swap.domain.models.ExpressDataError
import com.tangem.feature.swap.domain.models.SwapAmount
@@ -122,12 +123,13 @@ internal class SwapInteractorImpl @AssistedInject constructor(
.getOrElse { emptyList() }
val walletCurrencyStatusesExceptInitial = walletCurrencyStatuses
- .filter {
- val currencyFilter = it.currency.network.backendId != currency.network.backendId ||
- it.currency.getContractAddress() != currency.getContractAddress()
- val statusFilter = it.value is CryptoCurrencyStatus.Loaded || it.value is CryptoCurrencyStatus.NoAccount
- val notCustomTokenFilter = !it.currency.isCustom
- statusFilter && currencyFilter && notCustomTokenFilter
+ .filter { status ->
+ val isDifferentCurrency = status.currency.network.backendId != currency.network.backendId ||
+ status.currency.getContractAddress() != currency.getContractAddress()
+ val hasValidStatus =
+ status.value is CryptoCurrencyStatus.Loaded || status.value is CryptoCurrencyStatus.NoAccount
+ val isNotCustomToken = !status.currency.isCustom
+ hasValidStatus && isDifferentCurrency && isNotCustomToken
}
if (walletCurrencyStatusesExceptInitial.isEmpty()) {
@@ -169,15 +171,15 @@ internal class SwapInteractorImpl @AssistedInject constructor(
val walletAccountCurrencyStatusesExceptInitial = walletAccountCurrencyStatuses
.mapNotNull { accountStatus ->
- val filteredCurrencies = accountStatus.flattenCurrencies().filter {
- val currencyFilter = it.currency.network.backendId != currency.network.backendId ||
- it.currency.getContractAddress() != currency.getContractAddress()
+ val filteredCurrencies = accountStatus.flattenCurrencies().filter { status ->
+ val isDifferentCurrency = status.currency.network.backendId != currency.network.backendId ||
+ status.currency.getContractAddress() != currency.getContractAddress()
- val statusFilter =
- it.value is CryptoCurrencyStatus.Loaded || it.value is CryptoCurrencyStatus.NoAccount
- val notCustomTokenFilter = !it.currency.isCustom
+ val hasValidStatus =
+ status.value is CryptoCurrencyStatus.Loaded || status.value is CryptoCurrencyStatus.NoAccount
+ val isNotCustomToken = !status.currency.isCustom
- statusFilter && currencyFilter && notCustomTokenFilter
+ hasValidStatus && isDifferentCurrency && isNotCustomToken
}
if (filteredCurrencies.isNotEmpty()) {
@@ -228,9 +230,9 @@ internal class SwapInteractorImpl @AssistedInject constructor(
tokenInfoForFilter: (SwapPairLeast) -> LeastTokenInfo,
tokenInfoForAvailable: (SwapPairLeast) -> LeastTokenInfo,
): CurrenciesGroup {
- val filteredPairs = leastPairs.filter {
- tokenInfoForFilter(it).contractAddress == currency.getContractAddress() &&
- tokenInfoForFilter(it).network == currency.network.backendId
+ val filteredPairs = leastPairs.filter { pair ->
+ tokenInfoForFilter(pair).contractAddress == currency.getContractAddress() &&
+ tokenInfoForFilter(pair).network == currency.network.backendId
}
val availableCryptoCurrencies = cryptoCurrenciesList.mapNotNull { cryptoCurrencyStatus ->
@@ -261,16 +263,16 @@ internal class SwapInteractorImpl @AssistedInject constructor(
tokenInfoForFilter: (SwapPairLeast) -> LeastTokenInfo,
tokenInfoForAvailable: (SwapPairLeast) -> LeastTokenInfo,
): CurrenciesGroup {
- val filteredPairs = leastPairs.filter {
- tokenInfoForFilter(it).contractAddress == currency.getContractAddress() &&
- tokenInfoForFilter(it).network == currency.network.backendId
+ val filteredPairs = leastPairs.filter { pair ->
+ tokenInfoForFilter(pair).contractAddress == currency.getContractAddress() &&
+ tokenInfoForFilter(pair).network == currency.network.backendId
}
- val accountCurrencyList = cryptoCurrenciesList.mapNotNull { (account, currencyStatusList) ->
- val account = account as? Account.CryptoPortfolio ?: return@mapNotNull null
+ val accountCurrencyList = cryptoCurrenciesList.mapNotNull { (accountEntry, currencyStatusList) ->
+ val cryptoPortfolio = accountEntry as? Account.CryptoPortfolio ?: return@mapNotNull null
AccountSwapAvailability(
- account = account,
+ account = cryptoPortfolio,
currencyList = currencyStatusList.map { currencyStatus ->
val providers = findProvidersForPair(
cryptoCurrencyStatuses = currencyStatus,
@@ -280,7 +282,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
val isUnavailable = providers.isNullOrEmpty()
AccountSwapCurrency(
isAvailable = !isUnavailable,
- account = account,
+ account = cryptoPortfolio,
cryptoCurrencyStatus = currencyStatus,
providers = providers.orEmpty(),
)
@@ -304,13 +306,13 @@ internal class SwapInteractorImpl @AssistedInject constructor(
val requirements = getAssetRequirementsUseCase.invoke(userWalletId, cryptoCurrencyStatuses.currency).getOrNull()
val isAvailableForSwap = rampStateManager.checkAssetRequirements(requirements)
- return swapPairsLeastList.firstNotNullOfOrNull {
- val listTokenInfo = tokenInfoForAvailable(it)
+ return swapPairsLeastList.firstNotNullOfOrNull { pair ->
+ val listTokenInfo = tokenInfoForAvailable(pair)
if (cryptoCurrencyStatuses.currency.network.backendId == listTokenInfo.network &&
cryptoCurrencyStatuses.currency.getContractAddress() == listTokenInfo.contractAddress &&
isAvailableForSwap
) {
- it.providers
+ pair.providers
} else {
null
}
@@ -351,8 +353,8 @@ internal class SwapInteractorImpl @AssistedInject constructor(
amount = amount?.value,
contractAddress = permissionOptions.forTokenContractAddress,
spenderAddress = permissionOptions.spenderAddress,
- ).getOrElse {
- Timber.e(it, "Failed to create approveTransaction")
+ ).getOrElse { error ->
+ Timber.e(error, "Failed to create approveTransaction")
return SwapTransactionState.Error.UnknownError
}
@@ -450,6 +452,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
}.toMap()
}
+ @Suppress("LongMethod")
private suspend fun manageDex(
networkId: String,
fromToken: CryptoCurrencyStatus,
@@ -487,8 +490,13 @@ internal class SwapInteractorImpl @AssistedInject constructor(
val fromTokenAddress = getTokenAddress(fromToken.currency)
val isAllowedToSpend = maybeQuotes.fold(
ifRight = { quotes ->
- quotes.allowanceContract?.let {
- isAllowedToSpend(networkId, fromToken.currency, amount, it)
+ quotes.allowanceContract?.let { allowanceContract ->
+ isAllowedToSpend(
+ networkId = networkId,
+ fromToken = fromToken.currency,
+ amount = amount,
+ spenderAddress = allowanceContract,
+ )
} != false
},
ifLeft = { false },
@@ -626,7 +634,12 @@ internal class SwapInteractorImpl @AssistedInject constructor(
is TxFeeState.MultipleFeeState -> feeState.getFeeByType(selectedFee).feeValue
is TxFeeState.SingleFeeState -> feeState.fee.feeValue
}
- val balanceAfterTransaction = getCoinBalanceAfterTransaction(fromTokenStatus, amount, includeFeeInAmount, fee)
+ val balanceAfterTransaction = getCoinBalanceAfterTransaction(
+ fromTokenStatus = fromTokenStatus,
+ amount = amount,
+ includeFeeInAmount = includeFeeInAmount,
+ fee = fee,
+ )
val amountToRequest = if (includeFeeInAmount is IncludeFeeInAmount.Included) {
includeFeeInAmount.amountSubtractFee
} else {
@@ -866,8 +879,8 @@ internal class SwapInteractorImpl @AssistedInject constructor(
userWalletId = userWalletId,
network = currencyToSendStatus.currency.network,
txExtras = createDexTxExtras(dataToSign, currencyToSendStatus.currency.network, txFee.fee.getGasLimit()),
- ).getOrElse {
- Timber.e(it, "Failed to create swap dex tx data")
+ ).getOrElse { error ->
+ Timber.e(error, "Failed to create swap dex tx data")
return SwapTransactionState.Error.UnknownError
}
return handleSwapResult(
@@ -938,11 +951,13 @@ internal class SwapInteractorImpl @AssistedInject constructor(
)
return result.fold(
ifRight = { txHash ->
+ val networkAddress = currencyToSendStatus.value.networkAddress
+ val fromAddress = networkAddress?.defaultAddress?.value.orEmpty()
repository.exchangeSent(
userWallet = userWallet,
txId = swapData.transaction.txId,
fromNetwork = currencyToSendStatus.currency.network.backendId,
- fromAddress = currencyToSendStatus.value.networkAddress?.defaultAddress?.value.orEmpty(),
+ fromAddress = fromAddress,
payInAddress = payInAddress,
txHash = txHash,
payInExtraId = swapData.transaction.txExtraId,
@@ -1000,12 +1015,16 @@ internal class SwapInteractorImpl @AssistedInject constructor(
expressOperationType: ExpressOperationType,
isTangemPayWithdrawal: Boolean,
): SwapTransactionState {
+ val fromNetworkAddress = currencyToSend.value.networkAddress
+ val fromAddress = fromNetworkAddress?.defaultAddress?.value.orEmpty()
+ val toNetworkAddress = currencyToGet.value.networkAddress
+ val toAddress = toNetworkAddress?.defaultAddress?.value.orEmpty()
val exchangeData = repository.getExchangeData(
userWallet = userWallet,
fromContractAddress = currencyToSend.currency.getContractAddress(),
fromNetwork = currencyToSend.currency.network.backendId,
toContractAddress = currencyToGet.currency.getContractAddress(),
- fromAddress = currencyToSend.value.networkAddress?.defaultAddress?.value.orEmpty(),
+ fromAddress = fromAddress,
toNetwork = currencyToGet.currency.network.backendId,
fromAmount = amount.toStringWithRightOffset(),
fromDecimals = amount.decimals,
@@ -1013,10 +1032,10 @@ internal class SwapInteractorImpl @AssistedInject constructor(
providerId = swapProvider.providerId,
rateType = RateType.FLOAT,
expressOperationType = expressOperationType,
- toAddress = currencyToGet.value.networkAddress?.defaultAddress?.value.orEmpty(),
+ toAddress = toAddress,
refundAddress = currencyToSend.value.networkAddress?.defaultAddress?.value,
refundExtraId = null, // currently always null,
- ).getOrElse { return SwapTransactionState.Error.ExpressError(it) }
+ ).getOrElse { error -> return SwapTransactionState.Error.ExpressError(error) }
val exchangeDataCex =
exchangeData.transaction as? ExpressTransactionModel.CEX ?: return SwapTransactionState.Error.UnknownError
@@ -1063,8 +1082,8 @@ internal class SwapInteractorImpl @AssistedInject constructor(
destination = exchangeDataCex.txTo,
userWalletId = userWalletId,
network = currencyToSend.currency.network,
- ).getOrElse {
- Timber.e(it, "Failed to create swap CEX tx data")
+ ).getOrElse { error ->
+ Timber.e(error, "Failed to create swap CEX tx data")
return SwapTransactionState.Error.UnknownError
}
@@ -1079,14 +1098,16 @@ internal class SwapInteractorImpl @AssistedInject constructor(
)
val derivationPath = currencyToSend.currency.network.derivationPath.value
+ val cexNetworkAddress = currencyToSend.value.networkAddress
+ val cexFromAddress = cexNetworkAddress?.defaultAddress?.value.orEmpty()
return result.fold(
- ifLeft = { SwapTransactionState.Error.TransactionError(it) },
+ ifLeft = { error -> SwapTransactionState.Error.TransactionError(error) },
ifRight = { txHash ->
repository.exchangeSent(
userWallet = userWallet,
txId = exchangeDataCex.txId,
fromNetwork = currencyToSend.currency.network.backendId,
- fromAddress = currencyToSend.value.networkAddress?.defaultAddress?.value.orEmpty(),
+ fromAddress = cexFromAddress,
payInAddress = txData.destinationAddress,
txHash = txHash,
payInExtraId = exchangeDataCex.txExtraId,
@@ -1182,8 +1203,13 @@ internal class SwapInteractorImpl @AssistedInject constructor(
isReverseFromTo: Boolean,
): CryptoCurrencyStatus? {
val group = state.getGroupWithReverse(isReverseFromTo)
- return initialToCurrencyResolver.tryGetFromCache(userWallet, initialCryptoCurrency, state, isReverseFromTo)
- ?: initialToCurrencyResolver.tryGetWithMaxAmount(state, isReverseFromTo)
+ return initialToCurrencyResolver.tryGetFromCache(
+ userWallet = userWallet,
+ initialCryptoCurrency = initialCryptoCurrency,
+ state = state,
+ isReverseFromTo = isReverseFromTo,
+ )
+ ?: initialToCurrencyResolver.tryGetWithMaxAmount(state = state, isReverseFromTo = isReverseFromTo)
?: group.available.firstOrNull()?.currencyStatus
}
@@ -1193,9 +1219,18 @@ internal class SwapInteractorImpl @AssistedInject constructor(
isReverseFromTo: Boolean,
): AccountSwapCurrency? {
val group = state.getGroupWithReverse(isReverseFromTo)
- return initialToCurrencyResolver.tryGetFromCacheV2(userWallet, initialCryptoCurrency, state, isReverseFromTo)
- ?: initialToCurrencyResolver.tryGetWithMaxAmountV2(state, isReverseFromTo)
- ?: group.accountCurrencyList.firstNotNullOfOrNull { it.currencyList.firstOrNull { it.isAvailable } }
+ return initialToCurrencyResolver.tryGetFromCacheV2(
+ userWallet = userWallet,
+ initialCryptoCurrency = initialCryptoCurrency,
+ state = state,
+ isReverseFromTo = isReverseFromTo,
+ )
+ ?: initialToCurrencyResolver.tryGetWithMaxAmountV2(state = state, isReverseFromTo = isReverseFromTo)
+ ?: group.accountCurrencyList.firstNotNullOfOrNull { accountSwapAvailability ->
+ accountSwapAvailability.currencyList.firstOrNull { accountSwapCurrency ->
+ accountSwapCurrency.isAvailable
+ }
+ }
}
override fun getNativeToken(networkId: String): CryptoCurrency {
@@ -1367,7 +1402,9 @@ internal class SwapInteractorImpl @AssistedInject constructor(
swapAmount = amount,
quotesLoadedState = swapState,
isAllowedToSpend = isAllowedToSpend,
- spenderAddress = quoteModel.allowanceContract,
+ spenderAddress = requireNotNull(quoteModel.allowanceContract) {
+ "allowanceContract is required for DEX"
+ },
)
if (state !is SwapState.QuotesLoadedState) return state
state.copy(
@@ -1548,19 +1585,23 @@ internal class SwapInteractorImpl @AssistedInject constructor(
selectedFee: FeeType,
expressOperationType: ExpressOperationType,
): SwapState {
+ val fromNetworkAddress = fromToken.value.networkAddress
+ val dexFromAddress = fromNetworkAddress?.defaultAddress?.value.orEmpty()
+ val toNetworkAddress = toToken.value.networkAddress
+ val dexToAddress = toNetworkAddress?.defaultAddress?.value.orEmpty()
return repository.getExchangeData(
userWallet = userWallet,
fromContractAddress = fromToken.currency.getContractAddress(),
fromNetwork = fromToken.currency.network.backendId,
toContractAddress = toToken.currency.getContractAddress(),
- fromAddress = fromToken.value.networkAddress?.defaultAddress?.value.orEmpty(),
+ fromAddress = dexFromAddress,
toNetwork = toToken.currency.network.backendId,
fromAmount = amount.toStringWithRightOffset(),
fromDecimals = amount.decimals,
toDecimals = toToken.currency.decimals,
providerId = provider.providerId,
rateType = RateType.FLOAT,
- toAddress = toToken.value.networkAddress?.defaultAddress?.value.orEmpty(),
+ toAddress = dexToAddress,
refundAddress = fromToken.value.networkAddress?.defaultAddress?.value,
expressOperationType = expressOperationType,
).fold(
@@ -1813,7 +1854,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
fromAccount: Account.CryptoPortfolio?,
swapAmount: SwapAmount,
quotesLoadedState: SwapState.QuotesLoadedState,
- spenderAddress: String?,
+ spenderAddress: String,
isAllowedToSpend: Boolean,
): SwapState {
val fromToken = fromTokenStatus.currency
@@ -1837,7 +1878,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
val derivationPath = fromToken.network.derivationPath.value
// setting up amount for approve with given amount for swap [SwapApproveType.Limited]
val callData = SmartContractCallDataProviderFactory.getApprovalCallData(
- spenderAddress = requireNotNull(spenderAddress) { "Spender address is null" },
+ spenderAddress = spenderAddress,
amount = swapAmount.value.convertToSdkAmount(fromTokenStatus),
blockchain = fromToken.network.toBlockchain(),
)
@@ -2212,9 +2253,9 @@ internal class SwapInteractorImpl @AssistedInject constructor(
val token = tokens
.filterIsInstance()
- .find {
- it.contractAddress.equals(feePaidCurrency.contractAddress, ignoreCase = true) &&
- it.network.derivationPath == fromTokenStatus.currency.network.derivationPath
+ .find { cryptoToken ->
+ cryptoToken.contractAddress.equals(feePaidCurrency.contractAddress, ignoreCase = true) &&
+ cryptoToken.network.derivationPath == fromTokenStatus.currency.network.derivationPath
}
SwapFeeState.NotEnough(
@@ -2268,18 +2309,18 @@ internal class SwapInteractorImpl @AssistedInject constructor(
}
private suspend fun Set.getQuotesOrEmpty(): Set {
- return runCatching {
- val cachedQuotes = quotesRepository.getMultiQuoteSyncOrNull(currenciesIds = this)
+ return runSuspendCatching {
+ val cachedQuotes = quotesRepository.getMultiQuoteSyncOrNull(currenciesIds = this@getQuotesOrEmpty)
- val allQuotesFound = cachedQuotes?.all { it.value !is QuoteStatus.Empty } == true
+ val areAllQuotesFound = cachedQuotes?.all { quote -> quote.value !is QuoteStatus.Empty } == true
- if (allQuotesFound) return@runCatching cachedQuotes
+ if (areAllQuotesFound) return@runSuspendCatching cachedQuotes.orEmpty()
val currenciesIds = if (cachedQuotes.isNullOrEmpty()) {
- this
+ this@getQuotesOrEmpty
} else {
- cachedQuotes.mapNotNullTo(hashSetOf()) {
- if (it.value is QuoteStatus.Empty) it.rawCurrencyId else null
+ cachedQuotes.mapNotNullTo(hashSetOf()) { quote ->
+ if (quote.value is QuoteStatus.Empty) quote.rawCurrencyId else null
}
}
@@ -2287,10 +2328,11 @@ internal class SwapInteractorImpl @AssistedInject constructor(
params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null),
)
- quotesRepository.getMultiQuoteSyncOrNull(currenciesIds = this)
+ quotesRepository.getMultiQuoteSyncOrNull(currenciesIds = this@getQuotesOrEmpty).orEmpty()
+ }.getOrElse { e ->
+ Timber.e(e, "Failed to get quotes: ${e.message.orEmpty()}")
+ emptySet()
}
- .getOrNull()
- .orEmpty()
}
private fun isSolana(networkId: String): Boolean {
@@ -2302,7 +2344,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
return try {
SolanaTransactionHelper.removeSignaturesPlaceholders(hash)
} catch (e: Exception) {
- Timber.e("Failed to format the hash: ${e.message}")
+ Timber.e("Failed to format the hash: ${e.message.orEmpty()}")
hash
}
}
diff --git a/features/swap/impl/detekt-baseline-debug.xml b/features/swap/impl/detekt-baseline-debug.xml
deleted file mode 100644
index 72441faba2..0000000000
--- a/features/swap/impl/detekt-baseline-debug.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
- BooleanPropertyNaming:ChooseFeeBottomSheet.kt$val showDivider = content.feeItems.lastIndex != index
- BooleanPropertyNaming:SwapEvents.kt$SwapEvents.ChooseTokenScreenOpened$val availableTokens: Boolean
- BooleanPropertyNaming:SwapEvents.kt$SwapEvents.ChooseTokenScreenResult$val tokenChosen: Boolean
- BooleanPropertyNaming:SwapNotificationsFactory.kt$SwapNotificationsFactory$val needShowCoverWarning = quoteModel.preparedSwapConfigState.isBalanceEnough && quoteModel.permissionState !is PermissionDataState.PermissionLoading && feeEnoughState.feeCurrency != fromToken
- BooleanPropertyNaming:SwapSelectTokenStateHolder.kt$SwapSelectTokenStateHolder$val afterSearch: Boolean
- BooleanPropertyNaming:SwapSelectTokenStateHolder.kt$TokenToSelectState.TokenToSelect$val available: Boolean = true
- BooleanPropertyNaming:SwapStateHolder.kt$SwapButton$val enabled: Boolean
- BooleanPropertyNaming:SwapStateHolder.kt$TransactionCardType.ReadOnly$val showWarning: Boolean = false
- BooleanPropertyNaming:SwapSuccessStateHolder.kt$SwapSuccessStateHolder$val showStatusButton: Boolean
- CastNullableToNonNullableType:SwapModel.kt$SwapModel$as
- MaxChainedCallsOnSameLine:SwapModel.kt$SwapModel$it.value.toTokenInfo.cryptoCurrencyStatus.currency.decimals
- MaxChainedCallsOnSameLine:SwapNotificationsFactory.kt$SwapNotificationsFactory$quoteModel.fromTokenInfo.cryptoCurrencyStatus.currency.network.currencySymbol
- MultilineLambdaItParameter:AccountTokenItemConverter.kt$AccountTokenItemConverter${ TokenItemState.TitleState.Content( text = stringReference(value = it.currency.name), isAvailable = false, ) }
- MultilineLambdaItParameter:AccountTokenItemConverter.kt$AccountTokenItemConverter${ createSubtitleState( status = it, isAvailable = false, text = unavailableErrorText, ) }
- MultilineLambdaItParameter:AccountTokenItemConverter.kt$AccountTokenItemConverter${ createSubtitleState( status = it, isAvailable = true, text = stringReference(value = it.currency.symbol), ) }
- MultilineLambdaItParameter:ProviderItem.kt${ Text( text = if (it > 0) "+$it%" else "$it%", style = TangemTheme.typography.body2, color = textColor, modifier = Modifier.padding(start = TangemTheme.dimens.spacing4), overflow = TextOverflow.Ellipsis, maxLines = 1, ) }
- MultilineLambdaItParameter:ProviderItem.kt${ Text( text = it, style = TangemTheme.typography.caption2, color = TangemTheme.colors.text.primary1, ) }
- MultilineLambdaItParameter:ProviderItem.kt${ Text( text = it, style = TangemTheme.typography.caption2, color = TangemTheme.colors.text.tertiary, ) }
- MultilineLambdaItParameter:ProviderItem.kt${ Text( text = it, style = TangemTheme.typography.caption2, color = TangemTheme.colors.text.tertiary, modifier = Modifier.padding(start = TangemTheme.dimens.spacing4), ) }
- MultilineLambdaItParameter:ProviderItem.kt${ Text( text = it.resolveReference(), style = TangemTheme.typography.body2, color = TangemTheme.colors.text.tertiary, modifier = Modifier.padding(top = TangemTheme.dimens.spacing6), ) }
- MultilineLambdaItParameter:ProviderItem.kt${ Text( text = it.resolveReference(), style = TangemTheme.typography.body2, color = TangemTheme.colors.text.tertiary, overflow = TextOverflow.Ellipsis, maxLines = 1, ) }
- MultilineLambdaItParameter:StateBuilder.kt$StateBuilder${ LegalState( title = resourceReference(R.string.common_privacy_policy), link = it, onClick = actions.onLinkClick, ) }
- MultilineLambdaItParameter:StateBuilder.kt$StateBuilder${ LegalState( title = resourceReference(R.string.common_terms_of_use), link = it, onClick = actions.onLinkClick, ) }
- MultilineLambdaItParameter:StateBuilder.kt$StateBuilder${ it is SwapNotificationUM.Error || it is NotificationUM.Error || it is SwapNotificationUM.Warning.ExpressError || it is SwapNotificationUM.Warning.ExpressGeneralError || it is SwapNotificationUM.Warning.NoAvailableTokensToSwap || it is SwapNotificationUM.Warning.NeedReserveToCreateAccount || it is SwapNotificationUM.Info.PermissionNeeded }
- MultilineLambdaItParameter:StateBuilder.kt$StateBuilder${ it.convertToProviderBottomSheetState( pricesLowerBest = pricesLowerBest, onProviderSelect = actions.onProviderSelect, needApplyFCARestrictions = needApplyFCARestrictions, ) }
- MultilineLambdaItParameter:StateBuilder.kt$StateBuilder${ val selectedItem = when (it) { FeeType.NORMAL -> txFeeState.normalFee FeeType.PRIORITY -> txFeeState.priorityFee } actions.onSelectFeeType.invoke(selectedItem) }
- MultilineLambdaItParameter:StateBuilder.kt$StateBuilder${ val tokenInfo = tokenSwapInfoForProviders[it.id] if (it is ProviderState.Content && tokenInfo != null) { val rateString = tokenInfo.tokenAmount .getFormattedCryptoAmount(tokenInfo.cryptoCurrencyStatus.currency) it.copy( subtitle = stringReference(rateString), percentLowerThenBest = pricesLowerBest[it.id]?.let { percent -> PercentDifference.Value(percent) } ?: PercentDifference.Value(0f), ) } else { it } }
- MultilineLambdaItParameter:StateBuilder.kt$StateBuilder${ when (it) { is TokenToSelectState.TokenToSelect -> { it.copy( addedTokenBalanceData = it.addedTokenBalanceData?.copy(isBalanceHidden = isBalanceHidden), ) } is TokenToSelectState.Title -> { it } } }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ AccountCryptoCurrencyStatus( account = it.account, status = it.cryptoCurrencyStatus, ) }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ Timber.d("${coin.id} balance is ${it.value.amount}") dataState = dataState.copy( feePaidCryptoCurrency = getFeePaidCryptoCurrencyStatusSyncUseCase( userWalletId = userWalletId, cryptoCurrencyStatus = it, ).getOrNull() ?: it, ) uiState = if (isFromCurrency) { dataState = dataState.copy(fromCryptoCurrency = it) stateBuilder.updateSendCurrencyBalance(uiState, it) } else { dataState = dataState.copy(toCryptoCurrency = it) stateBuilder.updateReceiveCurrencyBalance(uiState, it) } startLoadingQuotesFromLastState(isSilent = true) }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ Timber.e("Error when loading quotes: $it") uiState = stateBuilder.addNotification(uiState, null) { startLoadingQuotesFromLastState() } }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ Timber.e(it) applyInitialTokenChoice( state = TokensDataStateExpress.EMPTY, selectedCurrency = null, selectedAccount = null, isReverseFromTo = isReverseFromTo, ) uiState = stateBuilder.createInitialErrorState( uiState, (it as? ExpressException)?.expressDataError?.code ?: ExpressDataError.UnknownError.code, ) { uiState = stateBuilder.createInitialLoadingState( initialCurrencyFrom = initialCurrencyFrom, initialCurrencyTo = initialCurrencyTo, fromNetworkInfo = initialCurrencyFrom.getNetworkInfo(), ) initTokens(isReverseFromTo) } }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ Timber.e(it) startLoadingQuotesFromLastState() makeDefaultAlert() }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ Timber.e(it.message.orEmpty()) makeDefaultAlert() }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ getAccountCurrencyStatusUseCase.invokeSync( userWalletId = userWalletId, currency = it, ).getOrNull() }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync( userWalletId = userWalletId, cryptoCurrencyId = it.id, ).getOrNull() }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ if (!it.value.fromTokenInfo.amountFiat.isNullOrZero() && !it.value.toTokenInfo.amountFiat.isNullOrZero()) { it.value.fromTokenInfo.amountFiat.divide( it.value.toTokenInfo.amountFiat, it.value.toTokenInfo.cryptoCurrencyStatus.currency.decimals, RoundingMode.HALF_UP, ) } else { BigDecimal.ZERO } }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ if (it.key != selectedProviderEntry.key) { val amount = it.value.toTokenInfo.tokenAmount.value val percentDiff = BigDecimal.ONE.minus( selectedProviderRate.divide(amount, RoundingMode.HALF_UP), ).multiply(hundredPercent) it.key.providerId to percentDiff.setScale(2, RoundingMode.HALF_UP).toFloat() } else { null } }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ isBalanceHidden = it.isBalanceHidden uiState = stateBuilder.updateBalanceHiddenState(uiState, isBalanceHidden) }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ it is SwapState.SwapError && ( it.error is ExpressDataError.ExchangeTooSmallAmountError || it.error is ExpressDataError.ExchangeTooBigAmountError ) }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ it.currencyStatus.currency.name.contains(searchQuery, ignoreCase = true) || it.currencyStatus.currency.symbol.contains(searchQuery, ignoreCase = true) }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ subscribeToCoinBalanceUpdates( userWalletId = userWalletId, coin = it, isFromCurrency = false, ) }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ subscribeToCoinBalanceUpdates( userWalletId = userWalletId, coin = it, isFromCurrency = true, ) }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ uiState = stateBuilder.dismissBottomSheet(uiState) dataState = dataState.copy(selectedFee = it) modelScope.launch(dispatchers.io) { startLoadingQuotesFromLastState(false) } }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ val balance = swapInteractor.getTokenBalance(it) onAmountChanged(balance.formatToUIRepresentation()) }
- MultilineLambdaItParameter:SwapModel.kt$SwapModel${ val provider = findAndSelectProvider(it) val swapState = dataState.lastLoadedSwapStates[provider] val fromToken = dataState.fromCryptoCurrency if (provider != null && swapState != null && fromToken != null) { analyticsEventHandler.send(SwapEvents.ProviderChosen(provider)) uiState = stateBuilder.dismissBottomSheet(uiState) setupLoadedState( provider = provider, state = swapState, fromToken = fromToken, ) } }
- MultilineLambdaItParameter:TransactionCard.kt${ Text( text = it, color = TangemTheme.colors.text.tertiary, style = TangemTheme.typography.body2, ) }
- MultilineLambdaItParameter:TransactionCard.kt${ Text( text = it, color = TangemTheme.colors.text.tertiary, style = TangemTheme.typography.body2, modifier = Modifier .align(Alignment.CenterVertically) .testTag(SwapTokenScreenTestTags.BALANCE), ) }
- MultilineLambdaItParameter:TransactionCard.kt${ Text( text = it, color = TangemTheme.colors.text.tertiary, style = TangemTheme.typography.body2, modifier = Modifier.defaultMinSize(minHeight = TangemTheme.dimens.size20), ) }
- NamedArguments:SwapModel.kt$SwapModel$PeriodicTask( UPDATE_DELAY, task = { uiState = stateBuilder.createSilentLoadState(uiState) runCatching(dispatchers.io) { dataState = dataState.copy( amount = amount, reduceBalanceBy = reduceBalanceBy, swapDataModel = null, approveDataModel = null, ) swapInteractor.findBestQuote( fromToken = fromToken, fromAccount = fromAccount, toToken = toToken, toAccount = toAccount, providers = toProvidersList, amountToSwap = amount, reduceBalanceBy = reduceBalanceBy, selectedFee = dataState.selectedFee?.feeType ?: FeeType.NORMAL, ) } }, onSuccess = { providersState -> if (providersState.isNotEmpty()) { val (provider, state) = updateLoadedQuotes(providersState) setupLoadedState(provider, state, fromToken) val successStates = providersState.getLastLoadedSuccessStates() val pricesLowerBest = getPricesLowerBest(provider.providerId, successStates) uiState = stateBuilder.updateProvidersBottomSheetContent( uiState = uiState, pricesLowerBest = pricesLowerBest, tokenSwapInfoForProviders = successStates.entries .associate { it.key.providerId to it.value.toTokenInfo }, ) } else { Timber.e("Accidentally empty quotes list") } }, onError = { Timber.e("Error when loading quotes: $it") uiState = stateBuilder.addNotification(uiState, null) { startLoadingQuotesFromLastState() } }, )
- NoNameShadowing:SwapModel.kt$SwapModel${ it.cryptoCurrencyStatus }
- NoNameShadowing:SwapModel.kt$SwapModel${ it.cryptoCurrencyStatus.currency.id.value == id }
- NoNameShadowing:SwapModel.kt$SwapModel${ it.key == selectedSwapProvider }
- NullableToStringCall:SwapModel.kt$SwapModel$${currencyStatus.value.amount}
- NullableToStringCall:SwapModel.kt$SwapModel$${it.value.amount}
- NullableToStringCall:TransactionCard.kt$data.toString()
- PropertyUsedBeforeDeclaration:SwapModel.kt$SwapModel$isAccountsMode
- SuspendFunSwallowedCancellation:SwapModel.kt$SwapModel$runCatching
- UnnecessaryEventHandlerParameter:ChooseFeeBottomSheet.kt$onReadMoreClick: (String) -> Unit
- UnnecessaryLet:SwapModel.kt$SwapModel$let { return nonEmptyStates.entries.first { it.key == selectedSwapProvider }.toPair() }
- UnusedImports:TransactionCard.kt$import com.tangem.domain.models.account.Account
- UseEmptyCounterpart:StoriesEvents.kt$StoriesEvents$mapOf()
- UseEmptyCounterpart:SwapEvents.kt$SwapEvents$mapOf()
- UseOrEmpty:StateBuilder.kt$StateBuilder$initialCurrencyTo?.symbol ?: ""
- UseOrEmpty:SwapModel.kt$SwapModel$receiveToken ?: ""
- UseOrEmpty:SwapScreenContent.kt$swapCardState.tokenIconUrl ?: ""
- VarCouldBeVal:SwapModel.kt$SwapModel$private var swapRouter: SwapRouter = SwapRouter(router = router)
-
-
diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/StoriesEvents.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/StoriesEvents.kt
index b7f89e9288..1174a84ccc 100644
--- a/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/StoriesEvents.kt
+++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/StoriesEvents.kt
@@ -6,7 +6,7 @@ import com.tangem.core.analytics.models.AnalyticsParam.Key.WATCHED
sealed class StoriesEvents(
event: String,
- params: Map = mapOf(),
+ params: Map = emptyMap(),
) : AnalyticsEvent("Stories", event, params) {
data class SwapStories(
diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/SwapEvents.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/SwapEvents.kt
index c1ee5ff99d..e1c2640942 100644
--- a/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/SwapEvents.kt
+++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/SwapEvents.kt
@@ -15,7 +15,7 @@ private const val PROMO_CATEGORY = "Promo"
sealed class SwapEvents(
event: String,
- params: Map = mapOf(),
+ params: Map = emptyMap(),
) : AnalyticsEvent(SWAP_CATEGORY, event, params) {
data class SwapScreenOpened(val token: String) : SwapEvents(
@@ -25,15 +25,15 @@ sealed class SwapEvents(
class SendTokenBalanceClicked : SwapEvents(event = "Send Token Balance Clicked")
- data class ChooseTokenScreenOpened(val availableTokens: Boolean) : SwapEvents(
+ data class ChooseTokenScreenOpened(val hasAvailableTokens: Boolean) : SwapEvents(
event = "Choose Token Screen Opened",
- params = mapOf("Available tokens" to if (availableTokens) "Yes" else "No"),
+ params = mapOf("Available tokens" to if (hasAvailableTokens) "Yes" else "No"),
)
- data class ChooseTokenScreenResult(val tokenChosen: Boolean, val token: String? = null) : SwapEvents(
+ data class ChooseTokenScreenResult(val isTokenChosen: Boolean, val token: String? = null) : SwapEvents(
event = "Choose Token Screen Result",
params = buildMap {
- put("Token Chosen", if (tokenChosen) "Yes" else "No")
+ put("Token Chosen", if (isTokenChosen) "Yes" else "No")
token?.let { put("Token", it) }
},
)
diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/AccountTokenItemConverter.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/AccountTokenItemConverter.kt
index f556cdf5e5..4315d780ac 100644
--- a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/AccountTokenItemConverter.kt
+++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/AccountTokenItemConverter.kt
@@ -45,11 +45,11 @@ internal class AccountTokenItemConverter(
fun createAvailableItemConverter(): TokenItemStateConverter {
return TokenItemStateConverter(
appCurrency = appCurrency,
- subtitleStateProvider = {
+ subtitleStateProvider = { status ->
createSubtitleState(
- status = it,
+ status = status,
isAvailable = true,
- text = stringReference(value = it.currency.symbol),
+ text = stringReference(value = status.currency.symbol),
)
},
subtitle2StateProvider = ::createSubtitle2State,
@@ -64,15 +64,15 @@ internal class AccountTokenItemConverter(
return TokenItemStateConverter(
appCurrency = appCurrency,
iconStateProvider = { CryptoCurrencyToIconStateConverter(isAvailable = false).convert(it) },
- titleStateProvider = {
+ titleStateProvider = { status ->
TokenItemState.TitleState.Content(
- text = stringReference(value = it.currency.name),
+ text = stringReference(value = status.currency.name),
isAvailable = false,
)
},
- subtitleStateProvider = {
+ subtitleStateProvider = { status ->
createSubtitleState(
- status = it,
+ status = status,
isAvailable = false,
text = unavailableErrorText,
)
diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt
index e9f9ec7e68..ba936978ec 100644
--- a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt
+++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt
@@ -58,7 +58,7 @@ internal class TokensDataConverter(
onSearchEntered = onSearchEntered,
onTokenSelected = onTokenSelected,
isBalanceHidden = isBalanceHiddenProvider(),
- afterSearch = group.isAfterSearch,
+ isAfterSearch = group.isAfterSearch,
)
}
@@ -71,7 +71,7 @@ internal class TokensDataConverter(
id = cryptoCurrencyStatus.currency.id.value,
name = cryptoCurrencyStatus.currency.name,
symbol = cryptoCurrencyStatus.currency.symbol,
- available = isAvailable,
+ isAvailable = isAvailable,
tokenIcon = convertIcon(cryptoCurrencyStatus.currency, isAvailable),
addedTokenBalanceData = TokenBalanceData(
amount = formatCryptoAmount(cryptoCurrencyStatus),
diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverterV2.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverterV2.kt
index 3dbd07cda3..90dd691aaa 100644
--- a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverterV2.kt
+++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverterV2.kt
@@ -60,7 +60,7 @@ internal class TokensDataConverterV2(
onSearchEntered = onSearchEntered,
onTokenSelected = onTokenSelected,
isBalanceHidden = isBalanceHidden,
- afterSearch = tokensDataState.isAfterSearch,
+ isAfterSearch = tokensDataState.isAfterSearch,
),
)
}
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 d5884d3b72..4cdd1f15ff 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
@@ -139,6 +139,7 @@ internal class SwapModel @Inject constructor(
private var initialToStatus: CryptoCurrencyStatus? = null
private var isBalanceHidden = true
+ private var isAccountsMode: Boolean = false
private val selectedAppCurrencyFlow: StateFlow = createSelectedAppCurrencyFlow()
@@ -151,7 +152,10 @@ internal class SwapModel @Inject constructor(
)
private val inputNumberFormatter =
- InputNumberFormatter(NumberFormat.getInstance(Locale.getDefault()) as DecimalFormat)
+ InputNumberFormatter(
+ NumberFormat.getInstance(Locale.getDefault()) as? DecimalFormat
+ ?: error("NumberFormat is not DecimalFormat"),
+ )
private val amountDebouncer = Debouncer()
private val singleTaskScheduler = SingleTaskScheduler