Updated on 2026-08-14

This commit is contained in:
Tangem 2023-11-03 14:25:03 +03:00
parent 63f6ae5dfa
commit 761f896656
12 changed files with 17 additions and 97 deletions

View file

@ -215,8 +215,6 @@ internal class DefaultCurrenciesRepository(
override suspend fun getMultiCurrencyWalletCurrency(
userWalletId: UserWalletId,
id: CryptoCurrency.ID,
contractAddress: String?,
derivationPath: Network.DerivationPath,
): CryptoCurrency = withContext(dispatchers.io) {
val userWallet = getUserWallet(userWalletId)
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true)
@ -227,10 +225,8 @@ internal class DefaultCurrenciesRepository(
responseCurrenciesFactory.createCurrency(
currencyId = id,
contractAddress = contractAddress,
response = response,
scanResponse = userWallet.scanResponse,
derivationPath = derivationPath.value,
)
}

View file

@ -4,10 +4,9 @@ import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.common.DerivationStyleProvider
import com.tangem.domain.common.TapWorkarounds.isTestCard
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.domain.common.extensions.toCoinId
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.common.util.derivationStyleProvider
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.tokens.model.CryptoCurrency
@ -18,26 +17,13 @@ internal class ResponseCryptoCurrenciesFactory {
fun createCurrency(
currencyId: CryptoCurrency.ID,
contractAddress: String?,
response: UserTokensResponse,
scanResponse: ScanResponse,
derivationPath: String?,
): CryptoCurrency {
val responseTokenId = currencyId.rawCurrencyId
val networkId = Blockchain.fromId(currencyId.rawNetworkId).toNetworkId()
val token = requireNotNull(
value = response.tokens
.find {
it.id == responseTokenId && it.networkId == networkId && it.derivationPath == derivationPath &&
it.contractAddress == contractAddress
},
lazyMessage = { "Unable find a token with provided TokenID($responseTokenId) and NetworkID($networkId)" },
)
return requireNotNull(createCurrency(token, scanResponse)) {
"Unable to create a currency with provided ID: $currencyId"
}
return response.tokens
.asSequence()
.mapNotNull { createCurrency(it, scanResponse) }
.first { it.id == currencyId }
}
fun createCurrencies(response: UserTokensResponse, scanResponse: ScanResponse): List<CryptoCurrency> {
@ -56,9 +42,8 @@ internal class ResponseCryptoCurrenciesFactory {
}
val cardDerivationStyleProvider = scanResponse.derivationStyleProvider
val card = scanResponse.card
if (card.isTestCard) {
if (scanResponse.cardTypesResolver.isTestCard()) {
blockchain = blockchain.getTestnetVersion() ?: blockchain
}

View file

@ -57,9 +57,7 @@ internal class UpdateWalletManagerResultFactory {
}
private fun getTokensAmounts(amounts: Set<Amount>): Set<CryptoCurrencyAmount> {
val mutableAmounts = hashSetOf<CryptoCurrencyAmount>()
return amounts.mapNotNullTo(mutableAmounts, ::createCurrencyAmount)
return amounts.mapNotNullTo(hashSetOf(), ::createCurrencyAmount)
}
private fun getDemoTokensAmounts(demoAmount: Amount, tokens: Set<Token>): Set<CryptoCurrencyAmount> {

View file

@ -36,20 +36,16 @@ class FetchCurrencyStatusUseCase(
*
* @param userWalletId The ID of the user's wallet.
* @param id The ID of the cryptocurrency.
* @param contractAddress The contract address of the crypto currency
* @param derivationPath currency derivation path.
* @param refresh Indicates whether to force a refresh of the status data.
* @return An [Either] representing success (Right) or an error (Left) in fetching the status.
*/
suspend operator fun invoke(
userWalletId: UserWalletId,
id: CryptoCurrency.ID,
contractAddress: String?,
derivationPath: Network.DerivationPath,
refresh: Boolean = false,
): Either<CurrencyStatusError, Unit> {
return either {
val currency = getCurrency(userWalletId, id, contractAddress, derivationPath)
val currency = getCurrency(userWalletId, id)
fetchCurrencyStatus(userWalletId, currency, refresh)
}
@ -91,17 +87,10 @@ class FetchCurrencyStatusUseCase(
private suspend fun Raise<CurrencyStatusError>.getCurrency(
userWalletId: UserWalletId,
id: CryptoCurrency.ID,
contractAddress: String?,
derivationPath: Network.DerivationPath,
): CryptoCurrency {
return catch(
block = {
currenciesRepository.getMultiCurrencyWalletCurrency(
userWalletId = userWalletId,
id = id,
contractAddress = contractAddress,
derivationPath = derivationPath,
)
currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, id)
},
) {
raise(CurrencyStatusError.DataError(it))

View file

@ -6,7 +6,6 @@ import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.domain.tokens.error.CurrencyStatusError
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.wallets.models.UserWalletId
@ -19,17 +18,13 @@ class GetCryptoCurrencyUseCase(
*
* @param userWalletId The ID of the user's wallet.
* @param id The ID of the cryptocurrency.
* @param contractAddress The contract address of the crypto currency
* @param derivationPath currency derivation path.
* @return An [Either] representing success (Right) or an error (Left) in fetching the status.
*/
suspend operator fun invoke(
userWalletId: UserWalletId,
id: CryptoCurrency.ID,
contractAddress: String?,
derivationPath: Network.DerivationPath,
): Either<CurrencyStatusError, CryptoCurrency> {
return either { getCurrency(userWalletId, id, contractAddress, derivationPath) }
return either { getCurrency(userWalletId, id) }
}
/**
@ -45,17 +40,10 @@ class GetCryptoCurrencyUseCase(
private suspend fun Raise<CurrencyStatusError>.getCurrency(
userWalletId: UserWalletId,
id: CryptoCurrency.ID,
contractAddress: String?,
derivationPath: Network.DerivationPath,
): CryptoCurrency {
return catch(
block = {
currenciesRepository.getMultiCurrencyWalletCurrency(
userWalletId,
id,
contractAddress,
derivationPath,
)
currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, id)
},
catch = { raise(CurrencyStatusError.DataError(it)) },
)

View file

@ -5,7 +5,6 @@ import com.tangem.domain.tokens.error.CurrencyStatusError
import com.tangem.domain.tokens.error.mapper.mapToCurrencyError
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.NetworksRepository
@ -33,16 +32,12 @@ class GetCurrencyStatusUpdatesUseCase(
*
* @param userWalletId The unique identifier of the user's wallet.
* @param currencyId The unique identifier of the cryptocurrency.
* @param contractAddress The contract address of the crypto currency
* @param derivationPath currency derivation path.
* @param isSingleWalletWithTokens Indicates whether the user wallet contains only one token on card (old cards)
* @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation.
*/
operator fun invoke(
userWalletId: UserWalletId,
currencyId: CryptoCurrency.ID,
contractAddress: String?,
derivationPath: Network.DerivationPath,
isSingleWalletWithTokens: Boolean,
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
return flow {
@ -50,8 +45,6 @@ class GetCurrencyStatusUpdatesUseCase(
getCurrency(
userWalletId = userWalletId,
currencyId = currencyId,
contractAddress = contractAddress,
derivationPath = derivationPath,
isSingleWalletWithTokens = isSingleWalletWithTokens,
),
)
@ -61,9 +54,7 @@ class GetCurrencyStatusUpdatesUseCase(
private suspend fun getCurrency(
userWalletId: UserWalletId,
currencyId: CryptoCurrency.ID,
derivationPath: Network.DerivationPath,
isSingleWalletWithTokens: Boolean,
contractAddress: String?,
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
val operations = CurrenciesStatusesOperations(
currenciesRepository = currenciesRepository,
@ -75,7 +66,7 @@ class GetCurrencyStatusUpdatesUseCase(
val currencyFlow = if (isSingleWalletWithTokens) {
operations.getCurrencyStatusSingleWalletWithTokensFlow(currencyId)
} else {
operations.getCurrencyStatusFlow(currencyId, contractAddress, derivationPath)
operations.getCurrencyStatusFlow(currencyId)
}
return currencyFlow.map { maybeCurrency ->
maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError)

View file

@ -35,7 +35,6 @@ class GetCurrencyWarningsUseCase(
networkId = currency.network.id,
currencyId = currency.id,
derivationPath = derivationPath,
contractAddress = (currency as? CryptoCurrency.Token)?.contractAddress,
isSingleWalletWithTokens = isSingleWalletWithTokens,
),
flowOf(walletManagersFacade.getRentInfo(userWalletId, currency.network)),
@ -63,7 +62,6 @@ class GetCurrencyWarningsUseCase(
userWalletId: UserWalletId,
networkId: Network.ID,
currencyId: CryptoCurrency.ID,
contractAddress: String?,
derivationPath: Network.DerivationPath,
isSingleWalletWithTokens: Boolean,
): Flow<List<CryptoCurrencyWarning>> {
@ -77,7 +75,7 @@ class GetCurrencyWarningsUseCase(
val currencyFlow = if (isSingleWalletWithTokens) {
operations.getCurrencyStatusSingleWalletWithTokensFlow(currencyId)
} else {
operations.getCurrencyStatusFlow(currencyId, contractAddress, derivationPath)
operations.getCurrencyStatusFlow(currencyId)
}
val networkFlow = if (isSingleWalletWithTokens) {
operations.getNetworkCoinForSingleWalletWithTokenFlow(networkId)

View file

@ -105,13 +105,9 @@ internal class CurrenciesStatusesOperations(
}
}
suspend fun getCurrencyStatusFlow(
currencyId: CryptoCurrency.ID,
contractAddress: String?,
derivationPath: Network.DerivationPath,
): Flow<Either<Error, CryptoCurrencyStatus>> {
suspend fun getCurrencyStatusFlow(currencyId: CryptoCurrency.ID): Flow<Either<Error, CryptoCurrencyStatus>> {
val currency = recover(
block = { getMultiCurrencyWalletCurrency(currencyId, contractAddress, derivationPath) },
block = { getMultiCurrencyWalletCurrency(currencyId) },
recover = { return flowOf(it.left()) },
)
@ -245,17 +241,11 @@ internal class CurrenciesStatusesOperations(
.onEmpty { emit(Error.EmptyCurrencies.left()) }
}
private suspend fun Raise<Error>.getMultiCurrencyWalletCurrency(
currencyId: CryptoCurrency.ID,
contractAddress: String?,
derivationPath: Network.DerivationPath,
): CryptoCurrency {
private suspend fun Raise<Error>.getMultiCurrencyWalletCurrency(currencyId: CryptoCurrency.ID): CryptoCurrency {
return Either.catch {
currenciesRepository.getMultiCurrencyWalletCurrency(
userWalletId = userWalletId,
id = currencyId,
contractAddress = contractAddress,
derivationPath = derivationPath,
)
}
.mapLeft { Error.DataError(it) }

View file

@ -127,18 +127,11 @@ interface CurrenciesRepository {
*
* @param userWalletId The unique identifier of the user wallet.
* @param id The unique identifier of the cryptocurrency to be retrieved.
* @param contractAddress The contract address of the crypto currency
* @param derivationPath currency derivation path.
* @return The cryptocurrency associated with the user wallet and ID.
* @throws com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If single-currency user wallet
* ID provided.
*/
suspend fun getMultiCurrencyWalletCurrency(
userWalletId: UserWalletId,
id: CryptoCurrency.ID,
contractAddress: String?,
derivationPath: Network.DerivationPath,
): CryptoCurrency
suspend fun getMultiCurrencyWalletCurrency(userWalletId: UserWalletId, id: CryptoCurrency.ID): CryptoCurrency
/**
* Get the coin for a specific network.

View file

@ -80,8 +80,6 @@ internal class MockCurrenciesRepository(
override suspend fun getMultiCurrencyWalletCurrency(
userWalletId: UserWalletId,
id: CryptoCurrency.ID,
contractAddress: String?,
derivationPath: Network.DerivationPath,
): CryptoCurrency {
val token = token.getOrElse { e -> throw e }

View file

@ -80,8 +80,6 @@ internal class SendViewModel @Inject constructor(
getCurrencyStatusUpdatesUseCase(
userWalletId = userWalletId,
currencyId = cryptoCurrency.id,
derivationPath = cryptoCurrency.network.derivationPath,
contractAddress = (cryptoCurrency as? CryptoCurrency.Token)?.contractAddress,
isSingleWalletWithTokens = isSingleWallet,
)
.flowWithLifecycle(owner.lifecycle)

View file

@ -160,8 +160,6 @@ internal class TokenDetailsViewModel @Inject constructor(
getCurrencyStatusUpdatesUseCase(
userWalletId = userWalletId,
currencyId = cryptoCurrency.id,
contractAddress = (cryptoCurrency as? CryptoCurrency.Token)?.contractAddress,
derivationPath = cryptoCurrency.network.derivationPath,
isSingleWalletWithTokens = wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(),
)
.distinctUntilChanged()
@ -456,8 +454,6 @@ internal class TokenDetailsViewModel @Inject constructor(
fetchCurrencyStatusUseCase(
userWalletId = userWalletId,
id = cryptoCurrency.id,
contractAddress = (cryptoCurrency as? CryptoCurrency.Token)?.contractAddress,
derivationPath = cryptoCurrency.network.derivationPath,
refresh = true,
)
},