Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-04 14:42:00 +03:00
parent f60ac156a9
commit 30ba741110

View file

@ -1,15 +1,89 @@
package com.tangem.domain.transaction.usecase.gasless
import arrow.core.Either
import arrow.core.left
import arrow.core.raise.Raise
import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.tokens.GetMultiCryptoCurrencyStatusUseCase
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.transaction.GaslessTransactionRepository
import com.tangem.domain.transaction.error.GetFeeError
import java.math.BigDecimal
class GetAvailableFeeTokensUseCase {
class GetAvailableFeeTokensUseCase(
private val gaslessTransactionRepository: GaslessTransactionRepository,
private val currenciesRepository: CurrenciesRepository,
private val getMultiCryptoCurrencyStatusUseCase: GetMultiCryptoCurrencyStatusUseCase,
) {
operator fun invoke(userWalletId: UserWalletId, network: Network): Either<GetFeeError, List<CryptoCurrencyStatus>> {
return GetFeeError.UnknownError.left()
/**
* Retrieves available tokens for gasless fee payment.
*
* @return List where first element is always native currency (for fallback)
*/
suspend operator fun invoke(
userWallet: UserWallet,
network: Network,
): Either<GetFeeError, List<CryptoCurrencyStatus>> {
return either {
catch(
block = {
val userCurrenciesStatuses = getMultiCryptoCurrencyStatusUseCase.invokeMultiWalletSync(
userWallet.walletId,
).getOrNull()
?: raiseIllegalStateError("currencies list is null for userWalletId=${userWallet.walletId}")
val nativeCurrencyStatus = getNativeCurrencyStatus(userWallet, network, userCurrenciesStatuses)
if (!gaslessTransactionRepository.isNetworkSupported(network)) {
return@either listOf(nativeCurrencyStatus)
}
val gaslessTokens = getGaslessTokens(userCurrenciesStatuses)
buildList {
add(nativeCurrencyStatus)
addAll(gaslessTokens)
}
},
catch = {
raise(GetFeeError.DataError(it))
},
)
}
}
private suspend fun Raise<GetFeeError>.getNativeCurrencyStatus(
userWallet: UserWallet,
network: Network,
userCurrenciesStatuses: List<CryptoCurrencyStatus>,
): CryptoCurrencyStatus {
val nativeCurrency = currenciesRepository.getNetworkCoin(
userWalletId = userWallet.walletId,
networkId = network.id,
derivationPath = network.derivationPath,
)
return userCurrenciesStatuses.find {
it.currency.id == nativeCurrency.id
} ?: raiseIllegalStateError("no native currency found")
}
private fun getGaslessTokens(userCurrenciesStatuses: List<CryptoCurrencyStatus>): List<CryptoCurrencyStatus> {
val supportedGaslessTokens = gaslessTransactionRepository.getSupportedTokens()
return userCurrenciesStatuses
.asSequence()
.filter { currencyStatus ->
currencyStatus.currency is CryptoCurrency.Token &&
currencyStatus.value.amount?.let { amount -> amount > BigDecimal.ZERO } == true &&
supportedGaslessTokens.contains(currencyStatus.currency)
}
.toList()
}
private fun Raise<GetFeeError>.raiseIllegalStateError(error: String): Nothing {
raise(GetFeeError.DataError(IllegalStateException(error)))
}
}