Updated on 2026-08-14
This commit is contained in:
parent
7cb4b57fe9
commit
cf79b3b9a8
6 changed files with 49 additions and 14 deletions
|
|
@ -38,9 +38,13 @@ internal object AccountDomainModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideUpdateCryptoPortfolioUseCase(
|
fun provideUpdateCryptoPortfolioUseCase(
|
||||||
|
singleAccountListFetcher: SingleAccountListFetcher,
|
||||||
accountsCRUDRepository: AccountsCRUDRepository,
|
accountsCRUDRepository: AccountsCRUDRepository,
|
||||||
): UpdateCryptoPortfolioUseCase {
|
): UpdateCryptoPortfolioUseCase {
|
||||||
return UpdateCryptoPortfolioUseCase(crudRepository = accountsCRUDRepository)
|
return UpdateCryptoPortfolioUseCase(
|
||||||
|
singleAccountListFetcher = singleAccountListFetcher,
|
||||||
|
crudRepository = accountsCRUDRepository,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,10 @@ internal class DefaultWalletAccountsFetcher @Inject constructor(
|
||||||
|
|
||||||
override suspend fun fetch(userWalletId: UserWalletId): GetWalletAccountsResponse {
|
override suspend fun fetch(userWalletId: UserWalletId): GetWalletAccountsResponse {
|
||||||
val savedAccountsResponse = getAccountsResponseStore(userWalletId = userWalletId).getSyncOrNull()
|
val savedAccountsResponse = getAccountsResponseStore(userWalletId = userWalletId).getSyncOrNull()
|
||||||
val accountsResponse = fetchWalletAccounts(userWalletId, savedAccountsResponse)
|
val fetchResult = fetchWalletAccounts(userWalletId, savedAccountsResponse)
|
||||||
|
val accountsResponse = fetchResult.accountsResponse
|
||||||
|
|
||||||
return when {
|
val updatedResponse = when {
|
||||||
accountsResponse.accounts.isEmpty() -> {
|
accountsResponse.accounts.isEmpty() -> {
|
||||||
initializeAccounts(userWalletId, accountsResponse)
|
initializeAccounts(userWalletId, accountsResponse)
|
||||||
}
|
}
|
||||||
|
|
@ -65,6 +66,12 @@ internal class DefaultWalletAccountsFetcher @Inject constructor(
|
||||||
}
|
}
|
||||||
else -> accountsResponse
|
else -> accountsResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fetchResult.error != null) {
|
||||||
|
throw fetchResult.error
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getSaved(userWalletId: UserWalletId): GetWalletAccountsResponse? {
|
override suspend fun getSaved(userWalletId: UserWalletId): GetWalletAccountsResponse? {
|
||||||
|
|
@ -123,7 +130,7 @@ internal class DefaultWalletAccountsFetcher @Inject constructor(
|
||||||
private suspend fun fetchWalletAccounts(
|
private suspend fun fetchWalletAccounts(
|
||||||
userWalletId: UserWalletId,
|
userWalletId: UserWalletId,
|
||||||
savedAccountsResponse: GetWalletAccountsResponse?,
|
savedAccountsResponse: GetWalletAccountsResponse?,
|
||||||
): GetWalletAccountsResponse {
|
): FetchResult {
|
||||||
return safeApiCall(
|
return safeApiCall(
|
||||||
call = {
|
call = {
|
||||||
val apiResponse = withContext(dispatchers.io) {
|
val apiResponse = withContext(dispatchers.io) {
|
||||||
|
|
@ -138,7 +145,7 @@ internal class DefaultWalletAccountsFetcher @Inject constructor(
|
||||||
val responseBody = apiResponse.bind()
|
val responseBody = apiResponse.bind()
|
||||||
store(userWalletId = userWalletId, response = responseBody)
|
store(userWalletId = userWalletId, response = responseBody)
|
||||||
|
|
||||||
responseBody
|
FetchResult(responseBody)
|
||||||
},
|
},
|
||||||
onError = { throwable ->
|
onError = { throwable ->
|
||||||
// pushWalletAccounts and storeWalletAccounts help to avoid cyclic dependency
|
// pushWalletAccounts and storeWalletAccounts help to avoid cyclic dependency
|
||||||
|
|
@ -211,4 +218,9 @@ internal class DefaultWalletAccountsFetcher @Inject constructor(
|
||||||
private fun getAccountsResponseStore(userWalletId: UserWalletId): AccountsResponseStore {
|
private fun getAccountsResponseStore(userWalletId: UserWalletId): AccountsResponseStore {
|
||||||
return accountsResponseStoreFactory.create(userWalletId = userWalletId)
|
return accountsResponseStoreFactory.create(userWalletId = userWalletId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class FetchResult(
|
||||||
|
val accountsResponse: GetWalletAccountsResponse,
|
||||||
|
val error: Throwable? = null,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.data.account.fetcher
|
package com.tangem.data.account.fetcher
|
||||||
|
|
||||||
|
import com.tangem.data.account.fetcher.DefaultWalletAccountsFetcher.FetchResult
|
||||||
import com.tangem.data.account.utils.DefaultWalletAccountsResponseFactory
|
import com.tangem.data.account.utils.DefaultWalletAccountsResponseFactory
|
||||||
import com.tangem.data.common.cache.etag.ETagsStore
|
import com.tangem.data.common.cache.etag.ETagsStore
|
||||||
import com.tangem.data.common.currency.UserTokensResponseAccountIdEnricher
|
import com.tangem.data.common.currency.UserTokensResponseAccountIdEnricher
|
||||||
|
|
@ -69,13 +70,15 @@ internal class FetchWalletAccountsErrorHandler @Inject constructor(
|
||||||
savedAccountsResponse: GetWalletAccountsResponse?,
|
savedAccountsResponse: GetWalletAccountsResponse?,
|
||||||
pushWalletAccounts: suspend (UserWalletId, List<WalletAccountDTO>) -> GetWalletAccountsResponse?,
|
pushWalletAccounts: suspend (UserWalletId, List<WalletAccountDTO>) -> GetWalletAccountsResponse?,
|
||||||
storeWalletAccounts: suspend (UserWalletId, GetWalletAccountsResponse) -> Unit,
|
storeWalletAccounts: suspend (UserWalletId, GetWalletAccountsResponse) -> Unit,
|
||||||
): GetWalletAccountsResponse {
|
): FetchResult {
|
||||||
val isResponseUpToDate = error.isNetworkError(code = Code.NOT_MODIFIED)
|
val isResponseUpToDate = error.isNetworkError(code = Code.NOT_MODIFIED)
|
||||||
if (isResponseUpToDate) {
|
if (isResponseUpToDate) {
|
||||||
Timber.e("ETag is up to date, no need to update accounts for wallet: $userWalletId")
|
Timber.e("ETag is up to date, no need to update accounts for wallet: $userWalletId")
|
||||||
return requireNotNull(savedAccountsResponse) {
|
val response = requireNotNull(savedAccountsResponse) {
|
||||||
"Saved accounts response is null for wallet: $userWalletId"
|
"Saved accounts response is null for wallet: $userWalletId"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return FetchResult(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
val response = savedAccountsResponse ?: createDefaultResponse(userWalletId)
|
val response = savedAccountsResponse ?: createDefaultResponse(userWalletId)
|
||||||
|
|
@ -95,7 +98,7 @@ internal class FetchWalletAccountsErrorHandler @Inject constructor(
|
||||||
|
|
||||||
storeWalletAccounts(userWalletId, response)
|
storeWalletAccounts(userWalletId, response)
|
||||||
|
|
||||||
return response
|
return FetchResult(response, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun createDefaultResponse(userWalletId: UserWalletId): GetWalletAccountsResponse {
|
private suspend fun createDefaultResponse(userWalletId: UserWalletId): GetWalletAccountsResponse {
|
||||||
|
|
|
||||||
|
|
@ -151,9 +151,9 @@ internal class DefaultAccountsCRUDRepository(
|
||||||
)
|
)
|
||||||
|
|
||||||
val syncedResponse = walletAccountsSaver.push(userWalletId = accountList.userWalletId, accounts = accountDTOs)
|
val syncedResponse = walletAccountsSaver.push(userWalletId = accountList.userWalletId, accounts = accountDTOs)
|
||||||
if (syncedResponse != null) {
|
?: error("Failed to push accounts for wallet: ${accountList.userWalletId}")
|
||||||
walletAccountsSaver.store(userWalletId = accountList.userWalletId, response = syncedResponse)
|
|
||||||
}
|
walletAccountsSaver.store(userWalletId = accountList.userWalletId, response = syncedResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun saveAccount(account: Account.CryptoPortfolio) {
|
override suspend fun saveAccount(account: Account.CryptoPortfolio) {
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,7 @@ internal class DefaultManageTokensRepository(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("CyclomaticComplexMethod")
|
||||||
private suspend fun createManagedCryptoCurrencyList(
|
private suspend fun createManagedCryptoCurrencyList(
|
||||||
params: ManageTokensListConfig.Account,
|
params: ManageTokensListConfig.Account,
|
||||||
userWallet: UserWallet?,
|
userWallet: UserWallet?,
|
||||||
|
|
@ -172,11 +173,15 @@ internal class DefaultManageTokensRepository(
|
||||||
updatedCoinsResponse: CoinsResponse,
|
updatedCoinsResponse: CoinsResponse,
|
||||||
): List<ManagedCryptoCurrency> {
|
): List<ManagedCryptoCurrency> {
|
||||||
val response = params.userWalletId?.let { userWalletId ->
|
val response = params.userWalletId?.let { userWalletId ->
|
||||||
if (loadUserTokensFromRemote && userWallet != null) {
|
val shouldFetch = loadUserTokensFromRemote && userWallet != null
|
||||||
|
|
||||||
|
val fetchedResponse = if (shouldFetch) {
|
||||||
runCatching { walletAccountsFetcher.fetch(userWalletId = userWallet.walletId) }.getOrNull()
|
runCatching { walletAccountsFetcher.fetch(userWalletId = userWallet.walletId) }.getOrNull()
|
||||||
} else {
|
} else {
|
||||||
walletAccountsFetcher.getSaved(userWalletId)
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchedResponse ?: walletAccountsFetcher.getSaved(userWalletId)
|
||||||
}
|
}
|
||||||
|
|
||||||
val accountId = when {
|
val accountId = when {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.tangem.domain.account.usecase
|
||||||
import arrow.core.Either
|
import arrow.core.Either
|
||||||
import arrow.core.getOrElse
|
import arrow.core.getOrElse
|
||||||
import arrow.core.raise.*
|
import arrow.core.raise.*
|
||||||
|
import com.tangem.domain.account.fetcher.SingleAccountListFetcher
|
||||||
import com.tangem.domain.account.models.AccountList
|
import com.tangem.domain.account.models.AccountList
|
||||||
import com.tangem.domain.account.repository.AccountsCRUDRepository
|
import com.tangem.domain.account.repository.AccountsCRUDRepository
|
||||||
import com.tangem.domain.models.account.Account
|
import com.tangem.domain.models.account.Account
|
||||||
|
|
@ -14,11 +15,13 @@ import com.tangem.domain.models.wallet.UserWalletId
|
||||||
/**
|
/**
|
||||||
* Use case for updating a crypto portfolio account.
|
* Use case for updating a crypto portfolio account.
|
||||||
*
|
*
|
||||||
|
* @property singleAccountListFetcher the fetcher used to retrieve a single account list
|
||||||
* @property crudRepository the repository used for performing CRUD operations on accounts
|
* @property crudRepository the repository used for performing CRUD operations on accounts
|
||||||
*
|
*
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
*/
|
*/
|
||||||
class UpdateCryptoPortfolioUseCase(
|
class UpdateCryptoPortfolioUseCase(
|
||||||
|
private val singleAccountListFetcher: SingleAccountListFetcher,
|
||||||
private val crudRepository: AccountsCRUDRepository,
|
private val crudRepository: AccountsCRUDRepository,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
@ -37,6 +40,8 @@ class UpdateCryptoPortfolioUseCase(
|
||||||
): Either<Error, Account.CryptoPortfolio> = either {
|
): Either<Error, Account.CryptoPortfolio> = either {
|
||||||
validate(accountName, icon)
|
validate(accountName, icon)
|
||||||
|
|
||||||
|
fetchAccountList(accountId.userWalletId)
|
||||||
|
|
||||||
val accountList = getAccountList(userWalletId = accountId.userWalletId)
|
val accountList = getAccountList(userWalletId = accountId.userWalletId)
|
||||||
|
|
||||||
val account = accountList.accounts
|
val account = accountList.accounts
|
||||||
|
|
@ -64,6 +69,12 @@ class UpdateCryptoPortfolioUseCase(
|
||||||
ensure(accountName != null || icon != null) { Error.NothingToUpdate }
|
ensure(accountName != null || icon != null) { Error.NothingToUpdate }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun Raise<Error>.fetchAccountList(userWalletId: UserWalletId) {
|
||||||
|
singleAccountListFetcher(params = SingleAccountListFetcher.Params(userWalletId)).onLeft {
|
||||||
|
raise(Error.DataOperationFailed(cause = it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun Raise<Error>.getAccountList(userWalletId: UserWalletId): AccountList {
|
private suspend fun Raise<Error>.getAccountList(userWalletId: UserWalletId): AccountList {
|
||||||
return catch(
|
return catch(
|
||||||
block = { crudRepository.getAccountListSync(userWalletId = userWalletId) },
|
block = { crudRepository.getAccountListSync(userWalletId = userWalletId) },
|
||||||
|
|
@ -91,7 +102,7 @@ class UpdateCryptoPortfolioUseCase(
|
||||||
|
|
||||||
private fun Raise<AccountList.Error>.checkDefaultName(accountList: AccountList, accountName: AccountName) {
|
private fun Raise<AccountList.Error>.checkDefaultName(accountList: AccountList, accountName: AccountName) {
|
||||||
withError({ AccountList.Error.DuplicateAccountNames }) {
|
withError({ AccountList.Error.DuplicateAccountNames }) {
|
||||||
Either.Companion.catch { crudRepository.checkDefaultAccountName(accountList, accountName) }.bind()
|
Either.catch { crudRepository.checkDefaultAccountName(accountList, accountName) }.bind()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue