From ee599a99c419e74acdbb883e76422989c8b1be12 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 25 Jun 2026 12:48:05 +0500 Subject: [PATCH] Updated on 2026-08-14 --- ...DefaultYieldSupplyTransactionRepository.kt | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyTransactionRepository.kt b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyTransactionRepository.kt index ac1c2517a6..92f845f1ea 100644 --- a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyTransactionRepository.kt +++ b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyTransactionRepository.kt @@ -18,8 +18,10 @@ import com.tangem.domain.utils.convertToSdkAmount import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.runSuspendCatching import com.tangem.utils.extensions.orZero import com.tangem.utils.logging.TangemLogger +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.withContext import java.math.BigDecimal @@ -97,7 +99,7 @@ internal class DefaultYieldSupplyTransactionRepository( cryptoCurrency: CryptoCurrency, ): BigDecimal? = withContext(dispatchers.io) { require(cryptoCurrency is CryptoCurrency.Token) - runCatching { + runSuspendCatching { val walletManager = walletManagersFacade.getOrCreateWalletManager( userWalletId = userWalletId, blockchain = cryptoCurrency.network.toBlockchain(), @@ -110,7 +112,7 @@ internal class DefaultYieldSupplyTransactionRepository( decimals = cryptoCurrency.decimals, ), ) - }.onFailure { TangemLogger.e("Error", it) }.getOrThrow() + }.logErrorUnlessCancellation().getOrThrow() } @Suppress("LongParameterList") @@ -201,27 +203,27 @@ internal class DefaultYieldSupplyTransactionRepository( cryptoCurrency: CryptoCurrency, ): String? = withContext(dispatchers.io) { require(cryptoCurrency is CryptoCurrency.Token) - runCatching { + runSuspendCatching { val walletManager = walletManagersFacade.getOrCreateWalletManager( userWalletId = userWalletId, blockchain = cryptoCurrency.network.toBlockchain(), derivationPath = cryptoCurrency.network.derivationPath.value, ) ?: error("Wallet manager not found") walletManager.calculateYieldModuleAddress() - }.onFailure { TangemLogger.e("Error", it) }.getOrThrow() + }.logErrorUnlessCancellation().getOrThrow() } override suspend fun getYieldContractAddress(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): String? = withContext(dispatchers.io) { require(cryptoCurrency is CryptoCurrency.Token) - runCatching { + runSuspendCatching { val walletManager = walletManagersFacade.getOrCreateWalletManager( userWalletId = userWalletId, blockchain = cryptoCurrency.network.toBlockchain(), derivationPath = cryptoCurrency.network.derivationPath.value, ) ?: error("Wallet manager not found") walletManager.getYieldModuleAddress() - }.onFailure { TangemLogger.e("Error", it) }.getOrThrow() + }.logErrorUnlessCancellation().getOrThrow() } override suspend fun wrapYieldSwapCallDataWithUpgradeIfNeeded( @@ -242,7 +244,7 @@ internal class DefaultYieldSupplyTransactionRepository( walletManager: WalletManager, cryptoCurrency: CryptoCurrency.Token, ): YieldSupplyStatus? = withContext(dispatchers.io) { - runCatching { + runSuspendCatching { val sdkSupplyStatus = walletManager.getYieldSupplyStatus(cryptoCurrency.contractAddress) val protocolBalance = if (sdkSupplyStatus?.isActive == true) { walletManager.getEffectiveProtocolBalance( @@ -269,7 +271,20 @@ internal class DefaultYieldSupplyTransactionRepository( isAllowedToSpend = isAllowedToSpend, effectiveProtocolBalance = protocolBalance, ) - }.onFailure { TangemLogger.e("Error", it) }.getOrNull() + }.logErrorUnlessCancellation().getOrThrow() + } + + /** + * Logs failures via [TangemLogger] but rethrows coroutine cancellation so a cancelled scope + * (e.g. leaving the yield-supply screen) cancels cleanly instead of being reported as a real + * error and swallowed to `null`. Covers both a raw [CancellationException] and one wrapped by + * the blockchain SDK as [BlockchainSdkError.WrappedThrowable] (carried in [Throwable.cause]), + * which is what `EthereumLikeJsonRpcProvider.post` throws when an in-flight RPC is cancelled. + */ + private fun Result.logErrorUnlessCancellation(): Result = onFailure { error -> + val cancellation = error as? CancellationException ?: error.cause as? CancellationException + if (cancellation != null) throw cancellation + TangemLogger.e("Error", error) } private fun createDeployTransaction(