Updated on 2026-08-14
This commit is contained in:
parent
5e6bf6aaae
commit
aaf4419ebe
12 changed files with 257 additions and 58 deletions
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.model
|
|||
import androidx.compose.runtime.Stable
|
||||
import arrow.core.getOrElse
|
||||
import arrow.core.merge
|
||||
import arrow.core.right
|
||||
import com.arkivanov.decompose.router.slot.SlotNavigation
|
||||
import com.arkivanov.decompose.router.slot.activate
|
||||
import com.arkivanov.decompose.router.slot.dismiss
|
||||
|
|
@ -31,12 +32,16 @@ import com.tangem.core.ui.extensions.wrappedList
|
|||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.haptic.VibratorHapticManager
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
|
||||
import com.tangem.domain.account.status.usecase.SaveCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.models.TokenReceiveNotification
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.network.NetworkAddress
|
||||
|
|
@ -141,6 +146,9 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
private val saveViewedYieldSupplyWarningUseCase: SaveViewedYieldSupplyWarningUseCase,
|
||||
private val saveViewedTokenReceiveWarningUseCase: SaveViewedTokenReceiveWarningUseCase,
|
||||
private val needShowYieldSupplyDepositedWarningUseCase: NeedShowYieldSupplyDepositedWarningUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val getAccountCryptoCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||
private val saveCryptoCurrenciesUseCase: SaveCryptoCurrenciesUseCase,
|
||||
) : Model(), TokenDetailsClickIntents, YieldSupplyDepositedWarningComponent.ModelCallback {
|
||||
|
||||
private val params = paramsContainer.require<TokenDetailsComponent.Params>()
|
||||
|
|
@ -158,6 +166,7 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
private val selectedAppCurrencyFlow: StateFlow<AppCurrency> = createSelectedAppCurrencyFlow()
|
||||
|
||||
private var cryptoCurrencyStatus: CryptoCurrencyStatus? = null
|
||||
private var account: Account.CryptoPortfolio? = null
|
||||
private var isBalanceLoadedEventSent = false
|
||||
private var expressTxStatusTaskScheduler = SingleTaskScheduler<PersistentList<ExpressTransactionStateUM>>()
|
||||
|
||||
|
|
@ -228,15 +237,26 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
private fun initButtons() {
|
||||
// we need also init buttons before start all loading to avoid buttons blocking
|
||||
modelScope.launch {
|
||||
val currentCryptoCurrencyStatus = getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencyId = cryptoCurrency.id,
|
||||
isSingleWalletWithTokens = false,
|
||||
).getOrNull()
|
||||
currentCryptoCurrencyStatus?.let {
|
||||
cryptoCurrencyStatus = it
|
||||
updateButtons(it)
|
||||
updateWarnings(it)
|
||||
val currentCryptoCurrencyStatus = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
getAccountCryptoCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = userWalletId,
|
||||
currency = cryptoCurrency,
|
||||
)
|
||||
.onSome { account = it.account }
|
||||
.getOrNull()
|
||||
?.status
|
||||
} else {
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencyId = cryptoCurrency.id,
|
||||
isSingleWalletWithTokens = false,
|
||||
).getOrNull()
|
||||
}
|
||||
|
||||
currentCryptoCurrencyStatus?.let { status ->
|
||||
cryptoCurrencyStatus = status
|
||||
updateButtons(currencyStatus = status)
|
||||
updateWarnings(cryptoCurrencyStatus = status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -308,12 +328,18 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun subscribeOnCurrencyStatusUpdates() {
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
isSingleWalletWithTokens = userWallet is UserWallet.Cold &&
|
||||
userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(),
|
||||
)
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
getAccountCryptoCurrencyStatusUseCase(userWalletId, cryptoCurrency)
|
||||
.onEach { account = it.account }
|
||||
.map { it.status.right() }
|
||||
} else {
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
isSingleWalletWithTokens = userWallet is UserWallet.Cold &&
|
||||
userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(),
|
||||
)
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.onEach { maybeCurrencyStatus ->
|
||||
internalUiState.value = stateFactory.getCurrencyLoadedBalanceState(maybeCurrencyStatus)
|
||||
|
|
@ -553,7 +579,7 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onReceiveClick(unavailabilityReason: ScenarioUnavailabilityReason) {
|
||||
val networkAddress = cryptoCurrencyStatus?.value?.networkAddress ?: return
|
||||
cryptoCurrencyStatus?.value?.networkAddress ?: return
|
||||
|
||||
analyticsEventsHandler.send(
|
||||
TokenScreenAnalyticsEvent.ButtonWithParams.ButtonReceive(
|
||||
|
|
@ -689,7 +715,18 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
|
||||
override fun onHideConfirmed() {
|
||||
modelScope.launch {
|
||||
removeCurrencyUseCase.invoke(userWalletId, cryptoCurrency)
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val accountId = account?.accountId
|
||||
|
||||
if (accountId == null) {
|
||||
Timber.e("Account ID is null, cannot hide currency ${cryptoCurrency.id}")
|
||||
return@launch
|
||||
}
|
||||
|
||||
saveCryptoCurrenciesUseCase(accountId = accountId, remove = cryptoCurrency)
|
||||
} else {
|
||||
removeCurrencyUseCase(userWalletId, cryptoCurrency)
|
||||
}
|
||||
.onLeft { Timber.e(it) }
|
||||
.onRight { router.popBackStack() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,17 @@ import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig
|
|||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.datasource.local.swap.ExpressAnalyticsStatus
|
||||
import com.tangem.datasource.local.swap.SwapTransactionStatusStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
|
||||
import com.tangem.domain.account.status.usecase.SaveCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.model.analytics.TokenExchangeAnalyticsEvent
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.swap.domain.SwapTransactionRepository
|
||||
import com.tangem.feature.swap.domain.api.SwapRepository
|
||||
import com.tangem.feature.swap.domain.models.domain.*
|
||||
|
|
@ -27,6 +31,7 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.map
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class ExchangeStatusFactory @AssistedInject constructor(
|
||||
|
|
@ -34,6 +39,9 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
|
|||
private val swapRepository: SwapRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||
private val saveCryptoCurrenciesUseCase: SaveCryptoCurrenciesUseCase,
|
||||
private val swapTransactionStatusStore: SwapTransactionStatusStore,
|
||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
@Assisted private val clickIntents: TokenDetailsClickIntents,
|
||||
|
|
@ -111,9 +119,41 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
|
|||
ifRight = { statusModel ->
|
||||
sendStatusUpdateAnalytics(statusModel, provider)
|
||||
|
||||
val refundTokenCurrency = addRefundCurrencyIfNeeded(statusModel, provider.type)
|
||||
val accountId = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = cryptoCurrency,
|
||||
)
|
||||
.map { it.account.accountId }
|
||||
.getOrNull()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
swapTransactionRepository.storeTransactionState(txId, statusModel, refundTokenCurrency)
|
||||
val refundTokenCurrency = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
if (accountId != null) {
|
||||
addRefundCurrencyIfNeededNew(
|
||||
accountId = accountId,
|
||||
status = statusModel,
|
||||
type = provider.type,
|
||||
)
|
||||
} else {
|
||||
Timber.e("Account ID is null, cannot add refund currency ${cryptoCurrency.id}")
|
||||
null
|
||||
}
|
||||
} else {
|
||||
addRefundCurrencyIfNeededLegacy(status = statusModel, type = provider.type)
|
||||
}
|
||||
|
||||
swapTransactionRepository.storeTransactionState(
|
||||
txId = txId,
|
||||
status = statusModel,
|
||||
accountWithCurrency = if (refundTokenCurrency != null) {
|
||||
Pair(accountId, refundTokenCurrency)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
)
|
||||
statusModel.copy(refundCurrency = refundTokenCurrency)
|
||||
},
|
||||
)
|
||||
|
|
@ -135,7 +175,7 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
|
|||
/**
|
||||
* For now do it only for dex-bridge provider
|
||||
*/
|
||||
private suspend fun addRefundCurrencyIfNeeded(
|
||||
private suspend fun addRefundCurrencyIfNeededLegacy(
|
||||
status: ExchangeStatusModel?,
|
||||
type: ExchangeProviderType,
|
||||
): CryptoCurrency? {
|
||||
|
|
@ -153,6 +193,27 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
|
|||
return null
|
||||
}
|
||||
|
||||
private suspend fun addRefundCurrencyIfNeededNew(
|
||||
accountId: AccountId,
|
||||
status: ExchangeStatusModel?,
|
||||
type: ExchangeProviderType,
|
||||
): CryptoCurrency? {
|
||||
status ?: return null
|
||||
if (type != ExchangeProviderType.DEX_BRIDGE) return null
|
||||
val refundNetwork = status.refundNetwork
|
||||
val refundContractAddress = status.refundContractAddress
|
||||
|
||||
if (refundNetwork == null || refundContractAddress == null) return null
|
||||
|
||||
return saveCryptoCurrenciesUseCase.add(
|
||||
accountId = accountId,
|
||||
contractAddress = refundContractAddress,
|
||||
networkId = refundNetwork,
|
||||
)
|
||||
.onLeft(Timber::e)
|
||||
.getOrNull()
|
||||
}
|
||||
|
||||
private fun getExchangeStatusState(
|
||||
savedTransactions: List<SavedSwapTransactionListModel>?,
|
||||
quoteStatuses: Set<QuoteStatus>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue