From 139ca0598566c49067eeb458c1cb09b8f8059014 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 May 2025 16:36:58 +0500 Subject: [PATCH 1/3] Updated on 2026-08-14 --- .../tangem/feature/wallet/child/wallet/model/WalletModel.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt index b06d42aa58..250b05849d 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt @@ -92,7 +92,6 @@ internal class WalletModel @Inject constructor( private val walletsUpdateJobHolder = JobHolder() private val refreshWalletJobHolder = JobHolder() - private val expressStatusJobHolder = JobHolder() private var needToRefreshWallet = false private var expressTxStatusTaskScheduler = SingleTaskScheduler() @@ -253,7 +252,6 @@ internal class WalletModel @Inject constructor( screenLifecycleProvider.isBackgroundState .onEach { isBackground -> expressTxStatusTaskScheduler.cancelTask() - expressStatusJobHolder.cancel() refreshWalletJobHolder.cancel() when { isBackground -> needToRefreshTimer() @@ -265,7 +263,6 @@ internal class WalletModel @Inject constructor( } } .launchIn(modelScope) - .saveIn(expressStatusJobHolder) } private fun subscribeOnExpressTransactionsUpdates(userWallet: UserWallet) { From 349d8fc7ddd63b880f0b9dc4c8c294b612b6d83f Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 May 2025 16:37:06 +0500 Subject: [PATCH 2/3] Updated on 2026-08-14 --- .../DefaultOnrampTransactionRepository.kt | 21 ++++++++++------ .../OnrampUpdateTransactionStatusUseCase.kt | 8 +++++- .../OnrampTransactionRepository.kt | 7 +++++- .../factory/express/OnrampStatusFactory.kt | 1 + .../wallet/domain/OnrampStatusFactory.kt | 1 + .../SingleWalletOnrampTransactionConverter.kt | 25 +++++++------------ 6 files changed, 37 insertions(+), 26 deletions(-) diff --git a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampTransactionRepository.kt b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampTransactionRepository.kt index 72a36a00db..6588bd6051 100644 --- a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampTransactionRepository.kt +++ b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampTransactionRepository.kt @@ -63,14 +63,19 @@ internal class DefaultOnrampTransactionRepository( }.map(transactionConverter::convert) } - override suspend fun updateTransactionStatus(txId: String, externalTxUrl: String, status: OnrampStatus.Status) = - withContext(dispatchers.io) { - val updatedTx = getTransactionById(txId)?.copy( - externalTxUrl = externalTxUrl, - status = status, - ) ?: return@withContext - storeTransaction(updatedTx) - } + override suspend fun updateTransactionStatus( + txId: String, + externalTxId: String, + externalTxUrl: String, + status: OnrampStatus.Status, + ) = withContext(dispatchers.io) { + val updatedTx = getTransactionById(txId)?.copy( + externalTxUrl = externalTxUrl, + externalTxId = externalTxId, + status = status, + ) ?: return@withContext + storeTransaction(updatedTx) + } override suspend fun removeTransaction(txId: String) { withContext(dispatchers.io) { diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampUpdateTransactionStatusUseCase.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampUpdateTransactionStatusUseCase.kt index 0c59d82df8..2b5e6836cc 100644 --- a/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampUpdateTransactionStatusUseCase.kt +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampUpdateTransactionStatusUseCase.kt @@ -10,9 +10,15 @@ class OnrampUpdateTransactionStatusUseCase( private val errorResolver: OnrampErrorResolver, ) { - suspend operator fun invoke(txId: String, externalTxUrl: String, status: OnrampStatus.Status) = Either.catch { + suspend operator fun invoke( + txId: String, + externalTxId: String, + externalTxUrl: String, + status: OnrampStatus.Status, + ) = Either.catch { onrampTransactionRepository.updateTransactionStatus( txId = txId, + externalTxId = externalTxId, externalTxUrl = externalTxUrl, status = status, ) diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampTransactionRepository.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampTransactionRepository.kt index f426a5ce30..a55ad0d3b8 100644 --- a/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampTransactionRepository.kt +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampTransactionRepository.kt @@ -14,7 +14,12 @@ interface OnrampTransactionRepository { fun getTransactions(userWalletId: UserWalletId, cryptoCurrencyId: CryptoCurrency.ID): Flow> - suspend fun updateTransactionStatus(txId: String, externalTxUrl: String, status: OnrampStatus.Status) + suspend fun updateTransactionStatus( + txId: String, + externalTxId: String, + externalTxUrl: String, + status: OnrampStatus.Status, + ) suspend fun removeTransaction(txId: String) } \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt index 76ca1a1052..2da3089940 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt @@ -125,6 +125,7 @@ internal class OnrampStatusFactory @AssistedInject constructor( onrampUpdateTransactionStatusUseCase( txId = txId, externalTxUrl = statusModel.externalTxUrl.orEmpty(), + externalTxId = statusModel.externalTxId.orEmpty(), status = statusModel.status, ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/OnrampStatusFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/OnrampStatusFactory.kt index b0347bbc46..5eb8b03010 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/OnrampStatusFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/OnrampStatusFactory.kt @@ -76,6 +76,7 @@ internal class OnrampStatusFactory @Inject constructor( onrampUpdateTransactionStatusUseCase( txId = txId, externalTxUrl = statusModel.externalTxUrl.orEmpty(), + externalTxId = statusModel.externalTxId.orEmpty(), status = statusModel.status, ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletOnrampTransactionConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletOnrampTransactionConverter.kt index ce57d2ac3a..6c056b3973 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletOnrampTransactionConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletOnrampTransactionConverter.kt @@ -157,7 +157,7 @@ internal class SingleWalletOnrampTransactionConverter( return ExpressStatusUM( title = resourceReference(R.string.common_transaction_status), - link = getStatusLink(status, externalTxUrl), + link = getStatusLink(externalTxUrl), statuses = statuses, ) } @@ -264,22 +264,15 @@ internal class SingleWalletOnrampTransactionConverter( state = getStatusState(OnrampStatus.Status.Sending), ) - private fun getStatusLink(status: OnrampStatus.Status, externalTxUrl: String?): ExpressLinkUM { + private fun getStatusLink(externalTxUrl: String?): ExpressLinkUM { if (externalTxUrl == null) return ExpressLinkUM.Empty - return when (status) { - OnrampStatus.Status.Verifying, - OnrampStatus.Status.Failed, - -> { - ExpressLinkUM.Content( - icon = R.drawable.ic_arrow_top_right_24, - text = resourceReference(R.string.common_go_to_provider), - onClick = { - clickIntents.onGoToProviderClick(externalTxUrl) - }, - ) - } - else -> ExpressLinkUM.Empty - } + return ExpressLinkUM.Content( + icon = R.drawable.ic_arrow_top_right_24, + text = resourceReference(R.string.common_go_to_provider), + onClick = { + clickIntents.onGoToProviderClick(externalTxUrl) + }, + ) } private fun OnrampStatus.Status.getStatusState(targetState: OnrampStatus.Status) = when { From 240dc3f3b84f727255db6ea7a235ebfc944e36ee Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 16 May 2025 16:07:29 +0500 Subject: [PATCH 3/3] Updated on 2026-08-14 --- .../wallet/child/wallet/model/WalletModel.kt | 58 ++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt index 250b05849d..2b9d3a318f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt @@ -46,10 +46,8 @@ import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION import com.tangem.features.pushnotifications.api.utils.getPushPermissionOrNull import com.tangem.utils.Provider import com.tangem.utils.coroutines.* -import kotlinx.coroutines.delay +import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import timber.log.Timber import javax.inject.Inject @@ -107,6 +105,7 @@ internal class WalletModel @Inject constructor( subscribeToUserWalletsUpdates() subscribeOnBalanceHiding() subscribeOnSelectedWalletFlow() + subscribeToScreenBackgroundState() subscribeOnPushNotificationsPermission() clickIntents.initialize(innerWalletRouter, modelScope) @@ -225,7 +224,6 @@ internal class WalletModel @Inject constructor( addReferralDeepLink(selectedWallet) walletDeepLinksHandler.registerForWallet(scope = modelScope, userWallet = selectedWallet) subscribeOnExpressTransactionsUpdates(selectedWallet) - subscribeToScreenBackgroundState(selectedWallet) } .flowOn(dispatchers.main) .launchIn(modelScope) @@ -248,39 +246,38 @@ internal class WalletModel @Inject constructor( // We need to update the current wallet quotes if the application was in the background for more than 10 seconds // and then returned to the foreground - private fun subscribeToScreenBackgroundState(userWallet: UserWallet) { + private fun subscribeToScreenBackgroundState() { screenLifecycleProvider.isBackgroundState .onEach { isBackground -> - expressTxStatusTaskScheduler.cancelTask() refreshWalletJobHolder.cancel() when { isBackground -> needToRefreshTimer() needToRefreshWallet && !isBackground -> { triggerRefreshWalletQuotes() - subscribeOnExpressTransactionsUpdates(userWallet) } - !isBackground -> subscribeOnExpressTransactionsUpdates(userWallet) } } .launchIn(modelScope) } private fun subscribeOnExpressTransactionsUpdates(userWallet: UserWallet) { - expressTxStatusTaskScheduler.cancelTask() - expressTxStatusTaskScheduler.scheduleTask( - modelScope, - PeriodicTask( - isDelayFirst = false, - delay = EXPRESS_STATUS_UPDATE_DELAY, - task = { - runCatching { - onrampStatusFactory.updateOnrmapTransactionStatuses(userWallet) - } - }, - onSuccess = { /* no-op */ }, - onError = { /* no-op */ }, - ), - ) + if (!userWallet.isMultiCurrency) { + expressTxStatusTaskScheduler.cancelTask() + expressTxStatusTaskScheduler.scheduleTask( + modelScope, + PeriodicTask( + isDelayFirst = false, + delay = EXPRESS_STATUS_UPDATE_DELAY, + task = { + runCatching { + onrampStatusFactory.updateOnrmapTransactionStatuses(userWallet) + } + }, + onSuccess = { /* no-op */ }, + onError = { /* no-op */ }, + ), + ) + } } private fun needToRefreshTimer() { @@ -295,9 +292,18 @@ internal class WalletModel @Inject constructor( val state = stateHolder.uiState.value val wallet = state.wallets.getOrNull(state.selectedWalletIndex) ?: return modelScope.launch { - refreshMultiCurrencyWalletQuotesUseCase(wallet.walletCardState.id).getOrElse { - Timber.e("Failed to refreshMultiCurrencyWalletQuotesUseCase $it") - } + awaitAll( + async { + refreshMultiCurrencyWalletQuotesUseCase(wallet.walletCardState.id).getOrElse { + Timber.e("Failed to refreshMultiCurrencyWalletQuotesUseCase $it") + } + }, + async { + getWalletsUseCase.invokeSync() + .firstOrNull { it.walletId == wallet.walletCardState.id } + ?.let(::subscribeOnExpressTransactionsUpdates) + }, + ) }.saveIn(refreshWalletJobHolder) }