diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/OnrampSuccessComponentUM.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/OnrampSuccessComponentUM.kt index cb5a0cd776..be7c79fafc 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/OnrampSuccessComponentUM.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/OnrampSuccessComponentUM.kt @@ -3,6 +3,7 @@ package com.tangem.features.onramp.success.entity import com.tangem.common.ui.expressStatus.state.ExpressStatusUM import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.ui.extensions.TextReference +import com.tangem.domain.onramp.model.OnrampStatus sealed class OnrampSuccessComponentUM { @@ -18,5 +19,6 @@ sealed class OnrampSuccessComponentUM { val providerName: TextReference, val providerImageUrl: String, val notification: NotificationUM?, + val activeStatus: OnrampStatus.Status, ) : OnrampSuccessComponentUM() } \ No newline at end of file diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/conterter/SetOnrampSuccessContentConverter.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/conterter/SetOnrampSuccessContentConverter.kt index 8cc5e95401..a88f509d15 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/conterter/SetOnrampSuccessContentConverter.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/conterter/SetOnrampSuccessContentConverter.kt @@ -51,6 +51,7 @@ internal class SetOnrampSuccessContentConverter( status = value.status, externalTxId = value.externalTxId, ), + activeStatus = value.status, notification = getNotification(status = value.status, externalTxUrl = value.externalTxUrl), ) } diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/previewdata/OnrampSuccessComponentUMPreviewData.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/previewdata/OnrampSuccessComponentUMPreviewData.kt index d7e355ba63..a984b3db97 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/previewdata/OnrampSuccessComponentUMPreviewData.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/entity/previewdata/OnrampSuccessComponentUMPreviewData.kt @@ -6,6 +6,7 @@ import com.tangem.common.ui.expressStatus.state.ExpressStatusItemUM import com.tangem.common.ui.expressStatus.state.ExpressStatusUM import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference +import com.tangem.domain.onramp.model.OnrampStatus import com.tangem.features.onramp.impl.R import com.tangem.features.onramp.success.entity.OnrampSuccessComponentUM import kotlinx.collections.immutable.persistentListOf @@ -24,6 +25,7 @@ internal data object OnrampSuccessComponentUMPreviewData { toAmount = stringReference("99.99 $"), currencyImageUrl = "", notification = null, + activeStatus = OnrampStatus.Status.Verifying, statusBlock = ExpressStatusUM( title = resourceReference(R.string.express_exchange_status_title), link = ExpressLinkUM.Empty, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/model/OnrampSuccessComponentModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/model/OnrampSuccessComponentModel.kt index 436bcd0791..ddc3cdb858 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/model/OnrampSuccessComponentModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/model/OnrampSuccessComponentModel.kt @@ -21,6 +21,7 @@ import com.tangem.domain.onramp.model.error.OnrampError import com.tangem.domain.tokens.GetCryptoCurrencyUseCase import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.analytics.TokenOnrampAnalyticsEvent +import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.onramp.component.OnrampSuccessComponent import com.tangem.features.onramp.impl.R @@ -29,6 +30,8 @@ import com.tangem.features.onramp.success.entity.OnrampSuccessComponentUM import com.tangem.features.onramp.success.entity.conterter.SetOnrampSuccessContentConverter import com.tangem.features.onramp.utils.sendOnrampErrorEvent import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.PeriodicTask +import com.tangem.utils.coroutines.SingleTaskScheduler import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -36,6 +39,7 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject +import kotlin.properties.Delegates @Suppress("LongParameterList") internal class OnrampSuccessComponentModel @Inject constructor( @@ -60,6 +64,10 @@ internal class OnrampSuccessComponentModel @Inject constructor( val state: StateFlow get() = _state.asStateFlow() + private var userWallet: UserWallet by Delegates.notNull() + private var cryptoCurrency: CryptoCurrency by Delegates.notNull() + private var expressTxStatusTaskScheduler = SingleTaskScheduler() + init { loadData() } @@ -82,67 +90,87 @@ internal class OnrampSuccessComponentModel @Inject constructor( showErrorAlert(error) }, ifRight = { transaction -> - loadTransactionStatus(transaction) + userWallet = getUserWalletUseCase(transaction.userWalletId).getOrElse { + Timber.e("UserWallet found") + // this case should never happened + showErrorAlert(OnrampError.DomainError("UserWallet not found")) + return@launch + } + cryptoCurrency = getCryptoCurrencyUseCase( + userWallet = userWallet, + cryptoCurrencyId = transaction.toCurrencyId, + ).getOrElse { + Timber.e("Crypto currency not found") + showErrorAlert(OnrampError.DomainError(null)) + return@launch + } + + startStatusUpdateTask(transaction) }, ) } } - private suspend fun loadTransactionStatus(transaction: OnrampTransaction) { - val userWallet = getUserWalletUseCase(transaction.userWalletId).getOrNull() - if (userWallet == null) { - Timber.e("UserWallet found") - // this case should never happened - showErrorAlert(OnrampError.DomainError("UserWallet not found")) - return - } - val cryptoCurrency = getCryptoCurrencyUseCase( - userWallet = userWallet, - cryptoCurrencyId = transaction.toCurrencyId, - ).getOrElse { - Timber.e("Crypto currency not found") - showErrorAlert(OnrampError.DomainError(null)) - return - } - - getOnrampStatusUseCase(userWallet = userWallet, txId = transaction.txId) - .fold( - ifLeft = { error -> - analyticsEventHandler.sendOnrampErrorEvent( - error = error, - tokenSymbol = cryptoCurrency.symbol, - providerName = transaction.providerName, - paymentMethod = transaction.paymentMethod, - ) - Timber.e(error.toString()) - showErrorAlert(error) - }, - ifRight = { status -> - analyticsEventHandler.send( - OnrampAnalyticsEvent.SuccessScreenOpened( - providerName = transaction.providerName, - currency = transaction.fromCurrency.code, - tokenSymbol = cryptoCurrency.symbol, - residence = transaction.residency, - paymentMethod = transaction.paymentMethod, - ), - ) - _state.update { - SetOnrampSuccessContentConverter( - cryptoCurrency = cryptoCurrency, - transaction = transaction, - goToProviderClick = ::goToProviderClick, - onCopyClick = ::onCopyClick, - ).convert(status) + private fun startStatusUpdateTask(transaction: OnrampTransaction) { + expressTxStatusTaskScheduler.cancelTask() + expressTxStatusTaskScheduler.scheduleTask( + modelScope, + PeriodicTask( + isDelayFirst = false, + delay = EXPRESS_STATUS_UPDATE_DELAY, + task = { + runCatching { + loadTransactionStatus(transaction) } - removeTransactionIfTerminalStatus( - cryptoCurrency = cryptoCurrency, - providerName = transaction.providerName, - paymentMethod = transaction.paymentMethod, - status = status, - ) }, - ) + onSuccess = { /* no-op */ }, + onError = { /* no-op */ }, + ), + ) + } + + private suspend fun loadTransactionStatus(transaction: OnrampTransaction) { + val isTerminal = (state.value as? OnrampSuccessComponentUM.Content)?.activeStatus?.isTerminal + if (isTerminal == null || isTerminal == false) { + getOnrampStatusUseCase(userWallet = userWallet, txId = transaction.txId) + .fold( + ifLeft = { error -> + analyticsEventHandler.sendOnrampErrorEvent( + error = error, + tokenSymbol = cryptoCurrency.symbol, + providerName = transaction.providerName, + paymentMethod = transaction.paymentMethod, + ) + Timber.e(error.toString()) + showErrorAlert(error) + }, + ifRight = { status -> + analyticsEventHandler.send( + OnrampAnalyticsEvent.SuccessScreenOpened( + providerName = transaction.providerName, + currency = transaction.fromCurrency.code, + tokenSymbol = cryptoCurrency.symbol, + residence = transaction.residency, + paymentMethod = transaction.paymentMethod, + ), + ) + _state.update { + SetOnrampSuccessContentConverter( + cryptoCurrency = cryptoCurrency, + transaction = transaction, + goToProviderClick = ::goToProviderClick, + onCopyClick = ::onCopyClick, + ).convert(status) + } + removeTransactionIfTerminalStatus( + cryptoCurrency = cryptoCurrency, + providerName = transaction.providerName, + paymentMethod = transaction.paymentMethod, + status = status, + ) + }, + ) + } } private fun showErrorAlert(error: OnrampError) { @@ -178,4 +206,8 @@ internal class OnrampSuccessComponentModel @Inject constructor( } } } + + private companion object { + const val EXPRESS_STATUS_UPDATE_DELAY = 10_000L + } } \ No newline at end of file