Updated on 2026-08-14

This commit is contained in:
Tangem 2023-03-06 13:22:16 +03:00
commit a1fe273205
7 changed files with 56 additions and 26 deletions

View file

@ -25,6 +25,10 @@ import timber.log.Timber
/**
[REDACTED_AUTHOR]
*/
@Deprecated(
message = "Use WalletStoresManager.fetch({userWalletId}, refresh = true) (to update all user wallet tokens)" +
"or WalletCurrenciesManager.update(...) (to update only one user wallet blockchain and its tokens) instead",
)
@Suppress("MagicNumber")
suspend fun WalletManager.safeUpdate(): Result<Wallet> = try {
val scanResponse = store.state.globalState.scanResponse

View file

@ -72,9 +72,12 @@ class TapWalletManager {
.doOnFailure { error ->
val errorAction = when (error) {
is WalletStoresError -> when (error) {
is WalletStoresError.FetchFiatRatesError,
is WalletStoresError.UpdateWalletManagerError,
-> WalletAction.LoadData.Failure(error = null)
is WalletStoresError.FetchFiatRatesError -> WalletAction.LoadData.Failure(error = null)
is WalletStoresError.UpdateWalletManagerTokensError -> WalletAction.LoadData.Failure(
error = TapError.WalletManager.InternalError(
message = error.cause.localizedMessage ?: error.customMessage,
),
)
is WalletStoresError.WalletManagerNotCreated -> WalletAction.LoadData.Failure(
error = TapError.WalletManager.CreationError,
)

View file

@ -35,10 +35,10 @@ sealed class WalletStoresError(code: Int) : TangemError(code) {
}
@Suppress("MagicNumber")
class UpdateWalletManagerError(
class UpdateWalletManagerTokensError(
blockchain: Blockchain,
override val cause: Throwable,
) : WalletStoresError(600015) {
override var customMessage: String = "Unable to update wallet manager for currency $blockchain: $cause"
override var customMessage: String = "Unable to update wallet manager tokens for currency $blockchain: $cause"
}
}

View file

@ -153,7 +153,7 @@ internal class DefaultWalletStoresManager(
.flatMapOnFailure { error ->
when (error) {
is WalletStoresError.WalletManagerNotCreated,
is WalletStoresError.UpdateWalletManagerError,
is WalletStoresError.UpdateWalletManagerTokensError,
-> storeWalletStore(null)
else -> CompletionResult.Failure(error)
}
@ -178,7 +178,7 @@ internal class DefaultWalletStoresManager(
.flatMapOnFailure { error ->
when (error) {
is WalletStoresError.WalletManagerNotCreated,
is WalletStoresError.UpdateWalletManagerError,
is WalletStoresError.UpdateWalletManagerTokensError,
-> CompletionResult.Success(Unit)
else -> CompletionResult.Failure(error)
}

View file

@ -2,7 +2,9 @@ package com.tangem.tap.domain.walletStores.repository.implementation
import com.tangem.blockchain.blockchains.solana.RentProvider
import com.tangem.blockchain.common.AmountType
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.BlockchainSdkError
import com.tangem.blockchain.common.TransactionHistoryProvider
import com.tangem.blockchain.common.Wallet
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.extensions.Result.Failure
@ -17,9 +19,9 @@ import com.tangem.common.map
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.domain.common.ScanResponse
import com.tangem.domain.common.util.UserWalletId
import com.tangem.tap.common.TestActions
import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.common.extensions.replaceByOrAdd
import com.tangem.tap.common.extensions.safeUpdate
import com.tangem.tap.domain.model.UserWallet
import com.tangem.tap.domain.model.WalletStoreModel
import com.tangem.tap.domain.walletStores.WalletStoresError
@ -37,6 +39,7 @@ import com.tangem.tap.domain.walletStores.repository.implementation.utils.update
import com.tangem.tap.domain.walletStores.storage.WalletManagerStorage
import com.tangem.tap.domain.walletStores.storage.WalletStoresStorage
import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.demo.isDemoCard
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.tap.features.wallet.models.PendingTransactionType
import com.tangem.tap.features.wallet.models.filterByCoin
@ -47,10 +50,12 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.math.BigDecimal
import kotlin.time.Duration
@Suppress("LargeClass")
internal class DefaultWalletAmountsRepository(
@ -118,8 +123,12 @@ internal class DefaultWalletAmountsRepository(
walletStores: List<WalletStoreModel>?,
fiatCurrency: FiatCurrency,
): CompletionResult<Unit> {
val walletStoresInternal = walletStores ?: getWalletStores(userWallets)
// FIXME: Use NetworkConnectionManager when it is added to DI
if (!NetworkConnectivity.getInstance().isOnlineOrConnecting()) {
return CompletionResult.Failure(WalletStoresError.NoInternetConnection)
}
val walletStoresInternal = walletStores ?: getWalletStores(userWallets)
val currencies = walletStoresInternal
.asSequence()
.flatMap { it.walletsData }
@ -177,6 +186,14 @@ internal class DefaultWalletAmountsRepository(
scanResponse: ScanResponse,
walletStores: List<WalletStoreModel>,
): CompletionResult<Unit> = coroutineScope {
// FIXME: Use NetworkConnectionManager when it is added to DI
if (!NetworkConnectivity.getInstance().isOnlineOrConnecting()) {
walletStores.forEach {
updateWalletStoreWithUnreachable(it)
}
return@coroutineScope CompletionResult.Failure(WalletStoresError.NoInternetConnection)
}
walletStores.map { walletStore ->
async {
// TODO: Find wallet manager via [com.tangem.tap.domain.walletStores.repository.WalletManagersRepository]
@ -206,8 +223,8 @@ internal class DefaultWalletAmountsRepository(
updateWalletStoreWithUnreachable(walletStore)
}
else -> {
withInternetConnection { walletManager.safeUpdate() }
.map { updateWalletManagerWithAmounts(userWalletId, walletManager) }
updateWalletManager(scanResponse, walletManager)
.map { updateWalletManagerInStorage(userWalletId, walletManager) }
.flatMap {
updateWalletStoreWithAmounts(
walletStore = walletStore,
@ -228,6 +245,24 @@ internal class DefaultWalletAmountsRepository(
}
}
private suspend fun updateWalletManager(
scanResponse: ScanResponse,
walletManager: WalletManager,
demoCardsDelay: Duration = with(Duration) { 500.milliseconds },
): CompletionResult<Unit> = catching {
if (scanResponse.isDemoCard() || TestActions.testAmountInjectionForWalletManagerEnabled) {
delay(demoCardsDelay)
TestActions.testAmountInjectionForWalletManagerEnabled = false
} else {
walletManager.update()
val wallet = walletManager.wallet
if (wallet.blockchain == Blockchain.SaltPay && walletManager is TransactionHistoryProvider) {
walletManager.getTransactionHistory(wallet.address, wallet.blockchain, wallet.getTokens())
}
}
}
private suspend fun fetchWalletStoreRentIfNeeded(
walletStore: WalletStoreModel,
walletManager: WalletManager,
@ -426,19 +461,7 @@ internal class DefaultWalletAmountsRepository(
}
}
private suspend inline fun withInternetConnection(crossinline block: suspend () -> Unit): CompletionResult<Unit> {
return if (!NetworkConnectivity.getInstance().isOnlineOrConnecting()) {
val error = WalletStoresError.NoInternetConnection
Timber.e(error)
CompletionResult.Failure(error)
} else {
withContext(Dispatchers.IO) {
catching { block() }
}
}
}
private suspend fun updateWalletManagerWithAmounts(
private suspend fun updateWalletManagerInStorage(
userWalletId: UserWalletId,
walletManager: WalletManager,
) = withContext(Dispatchers.Default) {

View file

@ -186,7 +186,7 @@ internal class DefaultWalletManagersRepository(
walletManager
}
.mapFailure {
val error = WalletStoresError.UpdateWalletManagerError(
val error = WalletStoresError.UpdateWalletManagerTokensError(
blockchain = walletManager.wallet.blockchain,
cause = it,
)

View file

@ -143,7 +143,7 @@ class WalletMiddleware {
Timber.e("Unable to proceed with changed network state, no user wallet selected")
return
}
scope.launch { globalState.tapWalletManager.loadData(selectedUserWallet) }
scope.launch { globalState.tapWalletManager.loadData(selectedUserWallet, refresh = true) }
}
is WalletAction.CopyAddress -> {
Analytics.send(Token.Receive.ButtonCopyAddress())