Updated on 2026-08-14
This commit is contained in:
parent
a51012484f
commit
32ced9df85
12 changed files with 87 additions and 33 deletions
|
|
@ -186,6 +186,7 @@ internal class DefaultCurrenciesRepository(
|
|||
override suspend fun getMultiCurrencyWalletCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CryptoCurrency = withContext(dispatchers.io) {
|
||||
val userWallet = getUserWallet(userWalletId)
|
||||
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true)
|
||||
|
|
@ -194,10 +195,14 @@ internal class DefaultCurrenciesRepository(
|
|||
"Unable to find tokens response for user wallet with provided ID: $userWalletId"
|
||||
}
|
||||
|
||||
responseCurrenciesFactory.createCurrency(id, response, userWallet.scanResponse)
|
||||
responseCurrenciesFactory.createCurrency(id, response, userWallet.scanResponse, derivationPath.value)
|
||||
}
|
||||
|
||||
override suspend fun getNetworkCoin(userWalletId: UserWalletId, networkId: Network.ID): CryptoCurrency.Coin {
|
||||
override suspend fun getNetworkCoin(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CryptoCurrency.Coin {
|
||||
val userWallet = getUserWallet(userWalletId)
|
||||
ensureIsCorrectUserWallet(userWallet = userWallet, isMultiCurrencyWalletExpected = true)
|
||||
|
||||
|
|
@ -207,15 +212,12 @@ internal class DefaultCurrenciesRepository(
|
|||
"Unable to find tokens response for user wallet with provided ID: $userWalletId"
|
||||
}
|
||||
val blockchain = Blockchain.fromId(networkId.value)
|
||||
val derivationPath = blockchain
|
||||
.derivationPath(userWallet.scanResponse.derivationStyleProvider.getDerivationStyle())
|
||||
?.rawPath
|
||||
val blockchainNetworkId = blockchain.toNetworkId()
|
||||
val coinId = blockchain.toCoinId()
|
||||
|
||||
val storedCoin = storedTokens.tokens
|
||||
.find {
|
||||
it.networkId == blockchain.toNetworkId() &&
|
||||
it.id == blockchain.toCoinId() &&
|
||||
it.derivationPath == derivationPath
|
||||
it.networkId == blockchainNetworkId && it.id == coinId && it.derivationPath == derivationPath.value
|
||||
} ?: error("Coin in this network $networkId not found")
|
||||
|
||||
val coin = responseCurrenciesFactory.createCurrency(storedCoin, userWallet.scanResponse)
|
||||
|
|
|
|||
|
|
@ -20,13 +20,10 @@ internal class ResponseCryptoCurrenciesFactory(private val demoConfig: DemoConfi
|
|||
currencyId: CryptoCurrency.ID,
|
||||
response: UserTokensResponse,
|
||||
scanResponse: ScanResponse,
|
||||
derivationPath: String?,
|
||||
): CryptoCurrency {
|
||||
val responseTokenId = currencyId.rawCurrencyId
|
||||
val blockchain = Blockchain.fromId(currencyId.rawNetworkId)
|
||||
val networkId = blockchain.toNetworkId()
|
||||
val derivationPath = blockchain
|
||||
.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle())
|
||||
?.rawPath
|
||||
val networkId = Blockchain.fromId(currencyId.rawNetworkId).toNetworkId()
|
||||
|
||||
val token = requireNotNull(
|
||||
value = response.tokens
|
||||
|
|
|
|||
|
|
@ -36,16 +36,18 @@ class FetchCurrencyStatusUseCase(
|
|||
*
|
||||
* @param userWalletId The ID of the user's wallet.
|
||||
* @param id The ID of the cryptocurrency.
|
||||
* @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,
|
||||
derivationPath: Network.DerivationPath,
|
||||
refresh: Boolean = false,
|
||||
): Either<CurrencyStatusError, Unit> {
|
||||
return either {
|
||||
val currency = getCurrency(userWalletId, id)
|
||||
val currency = getCurrency(userWalletId, id, derivationPath)
|
||||
|
||||
fetchCurrencyStatus(userWalletId, currency, refresh)
|
||||
}
|
||||
|
|
@ -87,8 +89,9 @@ class FetchCurrencyStatusUseCase(
|
|||
private suspend fun Raise<CurrencyStatusError>.getCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CryptoCurrency {
|
||||
return catch({ currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, id) }) {
|
||||
return catch({ currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, id, derivationPath) }) {
|
||||
raise(CurrencyStatusError.DataError(it))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ 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
|
||||
|
||||
|
|
@ -18,13 +19,15 @@ class GetCryptoCurrencyUseCase(
|
|||
*
|
||||
* @param userWalletId The ID of the user's wallet.
|
||||
* @param id The ID of the cryptocurrency.
|
||||
* @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,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): Either<CurrencyStatusError, CryptoCurrency> {
|
||||
return either { getCurrency(userWalletId, id) }
|
||||
return either { getCurrency(userWalletId, id, derivationPath) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -40,9 +43,10 @@ class GetCryptoCurrencyUseCase(
|
|||
private suspend fun Raise<CurrencyStatusError>.getCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CryptoCurrency {
|
||||
return catch(
|
||||
block = { currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, id) },
|
||||
block = { currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, id, derivationPath) },
|
||||
catch = { raise(CurrencyStatusError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ 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
|
||||
|
|
@ -32,20 +33,23 @@ class GetCurrencyStatusUpdatesUseCase(
|
|||
*
|
||||
* @param userWalletId The unique identifier of the user's wallet.
|
||||
* @param currencyId The unique identifier of the cryptocurrency.
|
||||
* @param derivationPath currency derivation path.
|
||||
* @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,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return flow {
|
||||
emitAll(getCurrency(userWalletId, currencyId))
|
||||
emitAll(getCurrency(userWalletId, currencyId, derivationPath))
|
||||
}.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
private suspend fun getCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
|
|
@ -54,7 +58,7 @@ class GetCurrencyStatusUpdatesUseCase(
|
|||
userWalletId = userWalletId,
|
||||
)
|
||||
|
||||
return operations.getCurrencyStatusFlow(currencyId).map { maybeCurrency ->
|
||||
return operations.getCurrencyStatusFlow(currencyId, derivationPath).map { maybeCurrency ->
|
||||
maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,12 +24,14 @@ class GetCurrencyWarningsUseCase(
|
|||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
currency: CryptoCurrency,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): Flow<Set<CryptoCurrencyWarning>> {
|
||||
return combine(
|
||||
getFeeWarningFlow(
|
||||
userWalletId = userWalletId,
|
||||
networkId = currency.network.id,
|
||||
currencyId = currency.id,
|
||||
derivationPath = derivationPath,
|
||||
),
|
||||
flowOf(walletManagersFacade.getRentInfo(userWalletId, currency.network)),
|
||||
flowOf(walletManagersFacade.getExistentialDeposit(userWalletId, currency.network)),
|
||||
|
|
@ -51,6 +53,7 @@ class GetCurrencyWarningsUseCase(
|
|||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): Flow<CryptoCurrencyWarning?> {
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
|
|
@ -60,8 +63,8 @@ class GetCurrencyWarningsUseCase(
|
|||
)
|
||||
|
||||
return combine(
|
||||
operations.getCurrencyStatusFlow(currencyId).map { it.getOrNull() },
|
||||
operations.getNetworkCoinFlow(networkId).map { it.getOrNull() },
|
||||
operations.getCurrencyStatusFlow(currencyId, derivationPath).map { it.getOrNull() },
|
||||
operations.getNetworkCoinFlow(networkId, derivationPath).map { it.getOrNull() },
|
||||
) { tokenStatus, coinStatus ->
|
||||
when {
|
||||
tokenStatus != null && coinStatus != null -> {
|
||||
|
|
|
|||
|
|
@ -23,12 +23,14 @@ class GetNetworkCoinStatusUseCase(
|
|||
operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return flow {
|
||||
emitAll(
|
||||
flow = getCurrency(
|
||||
userWalletId = userWalletId,
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -38,6 +40,7 @@ class GetNetworkCoinStatusUseCase(
|
|||
private suspend fun getCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
|
|
@ -46,7 +49,7 @@ class GetNetworkCoinStatusUseCase(
|
|||
userWalletId = userWalletId,
|
||||
)
|
||||
|
||||
return operations.getNetworkCoinFlow(networkId).map { maybeCurrency ->
|
||||
return operations.getNetworkCoinFlow(networkId, derivationPath).map { maybeCurrency ->
|
||||
maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,18 +67,24 @@ internal class CurrenciesStatusesOperations(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun getCurrencyStatusFlow(currencyId: CryptoCurrency.ID): Flow<Either<Error, CryptoCurrencyStatus>> {
|
||||
suspend fun getCurrencyStatusFlow(
|
||||
currencyId: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): Flow<Either<Error, CryptoCurrencyStatus>> {
|
||||
val currency = recover(
|
||||
block = { getMultiCurrencyWalletCurrency(currencyId) },
|
||||
block = { getMultiCurrencyWalletCurrency(currencyId, derivationPath) },
|
||||
recover = { return flowOf(it.left()) },
|
||||
)
|
||||
|
||||
return getCurrencyStatusFlow(currency)
|
||||
}
|
||||
|
||||
suspend fun getNetworkCoinFlow(networkId: Network.ID): Flow<Either<Error, CryptoCurrencyStatus>> {
|
||||
suspend fun getNetworkCoinFlow(
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): Flow<Either<Error, CryptoCurrencyStatus>> {
|
||||
val currency = recover(
|
||||
block = { getNetworkCoin(networkId) },
|
||||
block = { getNetworkCoin(networkId, derivationPath) },
|
||||
recover = { return flowOf(it.left()) },
|
||||
)
|
||||
|
||||
|
|
@ -178,14 +184,26 @@ internal class CurrenciesStatusesOperations(
|
|||
.onEmpty { emit(Error.EmptyCurrencies.left()) }
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getMultiCurrencyWalletCurrency(currencyId: CryptoCurrency.ID): CryptoCurrency {
|
||||
return Either.catch { currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, currencyId) }
|
||||
private suspend fun Raise<Error>.getMultiCurrencyWalletCurrency(
|
||||
currencyId: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CryptoCurrency {
|
||||
return Either.catch {
|
||||
currenciesRepository.getMultiCurrencyWalletCurrency(
|
||||
userWalletId,
|
||||
currencyId,
|
||||
derivationPath,
|
||||
)
|
||||
}
|
||||
.mapLeft { Error.DataError(it) }
|
||||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getNetworkCoin(networkId: Network.ID): CryptoCurrency {
|
||||
return Either.catch { currenciesRepository.getNetworkCoin(userWalletId, networkId) }
|
||||
private suspend fun Raise<Error>.getNetworkCoin(
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CryptoCurrency {
|
||||
return Either.catch { currenciesRepository.getNetworkCoin(userWalletId, networkId, derivationPath) }
|
||||
.mapLeft { Error.DataError(it) }
|
||||
.bind()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,19 +98,29 @@ interface CurrenciesRepository {
|
|||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @param id The unique identifier of the cryptocurrency to be retrieved.
|
||||
* @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): CryptoCurrency
|
||||
suspend fun getMultiCurrencyWalletCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CryptoCurrency
|
||||
|
||||
/**
|
||||
* Get the coin for a specific network.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @param networkId The unique identifier of the network.
|
||||
* @param derivationPath currency derivation path.
|
||||
*/
|
||||
suspend fun getNetworkCoin(userWalletId: UserWalletId, networkId: Network.ID): CryptoCurrency.Coin
|
||||
suspend fun getNetworkCoin(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CryptoCurrency.Coin
|
||||
|
||||
/**
|
||||
* Determines whether the tokens within a specific multi-currency user wallet are grouped.
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ internal class MockCurrenciesRepository(
|
|||
override suspend fun getMultiCurrencyWalletCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CryptoCurrency {
|
||||
val token = token.getOrElse { e -> throw e }
|
||||
|
||||
|
|
@ -75,7 +76,11 @@ internal class MockCurrenciesRepository(
|
|||
return token
|
||||
}
|
||||
|
||||
override suspend fun getNetworkCoin(userWalletId: UserWalletId, networkId: Network.ID): CryptoCurrency.Coin {
|
||||
override suspend fun getNetworkCoin(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CryptoCurrency.Coin {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
getCurrencyWarningsUseCase.invoke(
|
||||
userWalletId = selectedWallet.walletId,
|
||||
currency = cryptoCurrency,
|
||||
derivationPath = cryptoCurrency.network.derivationPath,
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
.onEach { uiState = stateFactory.getStateWithNotifications(it) }
|
||||
|
|
@ -151,6 +152,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
getCurrencyStatusUpdatesUseCase(
|
||||
userWalletId = selectedWallet.walletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
derivationPath = cryptoCurrency.network.derivationPath,
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
.onEach { either ->
|
||||
|
|
@ -247,6 +249,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
getNetworkCoinStatusUseCase(
|
||||
userWalletId = wallet.walletId,
|
||||
networkId = status.currency.network.id,
|
||||
derivationPath = status.currency.network.derivationPath,
|
||||
)
|
||||
.take(count = 1)
|
||||
.collectLatest {
|
||||
|
|
@ -373,6 +376,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
fetchCurrencyStatusUseCase.invoke(
|
||||
userWalletId = wallet.walletId,
|
||||
id = cryptoCurrency.id,
|
||||
derivationPath = cryptoCurrency.network.derivationPath,
|
||||
refresh = true,
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -579,6 +579,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
getNetworkCoinStatusUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
networkId = cryptoCurrencyStatus.currency.network.id,
|
||||
derivationPath = cryptoCurrencyStatus.currency.network.derivationPath,
|
||||
)
|
||||
.take(count = 1)
|
||||
.collectLatest {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue