diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index 8e58e90e09..65df536429 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -53,18 +53,6 @@ internal object TokensDomainModule { return DefaultTokensFeatureToggles(featureTogglesManager = featureTogglesManager) } - @Provides - @Singleton - fun provideGetCurrencyUseCase( - baseCurrencyStatusOperations: BaseCurrencyStatusOperations, - dispatchers: CoroutineDispatcherProvider, - ): GetSingleCryptoCurrencyStatusUseCase { - return GetSingleCryptoCurrencyStatusUseCase( - currencyStatusOperations = baseCurrencyStatusOperations, - dispatchers = dispatchers, - ) - } - @Provides @Singleton fun provideGetCurrencyWarningsUseCase( diff --git a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt index 52ecf3a396..a218b25669 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt @@ -1,13 +1,13 @@ package com.tangem.tap.di.domain import com.tangem.data.wallets.hot.TangemHotWalletSigner +import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.demo.models.DemoConfig import com.tangem.domain.networks.single.SingleNetworkStatusFetcher import com.tangem.domain.networks.single.SingleNetworkStatusSupplier import com.tangem.domain.notifications.repository.PushNotificationsRepository import com.tangem.domain.tokens.GetMultiCryptoCurrencyStatusUseCase -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.GetViewedTokenReceiveWarningUseCase import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier import com.tangem.domain.tokens.repository.CurrenciesRepository @@ -344,13 +344,13 @@ internal object TransactionDomainModule { fun provideCreateAndSendGaslessTransactionUseCase( walletManagersFacade: WalletManagersFacade, gaslessTransactionRepository: GaslessTransactionRepository, - getSingCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, + singleAccountListSupplier: SingleAccountListSupplier, cardSdkConfigRepository: CardSdkConfigRepository, tangemHotWalletSignerFactory: TangemHotWalletSigner.Factory, ): CreateAndSendGaslessTransactionUseCase { return CreateAndSendGaslessTransactionUseCase( walletManagersFacade = walletManagersFacade, - getSingleCryptoCurrencyStatusUseCase = getSingCryptoCurrencyStatusUseCase, + singleAccountListSupplier = singleAccountListSupplier, gaslessTransactionRepository = gaslessTransactionRepository, cardSdkConfigRepository = cardSdkConfigRepository, getHotWalletSigner = tangemHotWalletSignerFactory::create, diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthTxHelper.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthTxHelper.kt index 3526fb2d8c..80da92856a 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthTxHelper.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthTxHelper.kt @@ -1,5 +1,6 @@ package com.tangem.data.walletconnect.network.ethereum +import arrow.core.getOrElse import com.domain.blockaid.models.transaction.CheckTransactionResult import com.domain.blockaid.models.transaction.SimulationResult import com.domain.blockaid.models.transaction.simultation.ApproveInfo @@ -17,16 +18,17 @@ import com.tangem.blockchainsdk.utils.toBlockchain import com.tangem.blockchainsdk.utils.toCoinId import com.tangem.common.extensions.hexToBytes import com.tangem.data.common.currency.getCoinId +import com.tangem.domain.account.status.utils.CryptoCurrencyOperations.getCryptoCurrency +import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.transaction.usecase.GetEthSpecificFeeUseCase import com.tangem.domain.walletconnect.model.WcApprovedAmount import com.tangem.domain.walletconnect.model.WcEthTransactionParams import javax.inject.Inject internal class WcEthTxHelper @Inject constructor( - private val getSingleCryptoCurrency: GetSingleCryptoCurrencyStatusUseCase, + private val singleAccountListSupplier: SingleAccountListSupplier, private val ethSpecificFee: GetEthSpecificFeeUseCase, ) { @@ -34,10 +36,19 @@ internal class WcEthTxHelper @Inject constructor( val gasLimit = txParams.gas?.hexToBigInteger() ?: return null val gasPrice = txParams.gasPrice?.hexToBigInteger() val coinId = getCoinId(network, network.toBlockchain().toCoinId()) - val currency = getSingleCryptoCurrency.invokeMultiWalletSync(userWallet.walletId, coinId) - .map { it.currency } - .getOrNull() ?: return null - return ethSpecificFee(userWallet, currency, gasLimit, gasPrice) + + val currency = singleAccountListSupplier.getSyncOrNull(userWalletId = userWallet.walletId) + .getCryptoCurrency(currencyId = coinId, network = network) + .getOrElse { + return null + } + + return ethSpecificFee( + userWallet = userWallet, + cryptoCurrency = currency, + gasLimit = gasLimit, + gasPrice = gasPrice, + ) .map { it.minimum } .getOrNull() } diff --git a/domain/account/src/main/java/com/tangem/domain/account/supplier/SingleAccountListSupplier.kt b/domain/account/src/main/java/com/tangem/domain/account/supplier/SingleAccountListSupplier.kt index 91719dd554..1eb9756b6a 100644 --- a/domain/account/src/main/java/com/tangem/domain/account/supplier/SingleAccountListSupplier.kt +++ b/domain/account/src/main/java/com/tangem/domain/account/supplier/SingleAccountListSupplier.kt @@ -21,4 +21,10 @@ abstract class SingleAccountListSupplier( params = SingleAccountListProducer.Params(userWalletId = userWalletId), ) } + + suspend fun getSyncOrNull(userWalletId: UserWalletId): AccountList? { + return getSyncOrNull( + params = SingleAccountListProducer.Params(userWalletId = userWalletId), + ) + } } \ No newline at end of file diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/supplier/SingleAccountStatusListSupplier.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/supplier/SingleAccountStatusListSupplier.kt index 6177e2cde5..8e280e81df 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/supplier/SingleAccountStatusListSupplier.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/supplier/SingleAccountStatusListSupplier.kt @@ -20,4 +20,9 @@ abstract class SingleAccountStatusListSupplier( val params = SingleAccountStatusListProducer.Params(userWalletId) return this.invoke(params) } + + suspend fun getSyncOrNull(userWalletId: UserWalletId): AccountStatusList? { + val params = SingleAccountStatusListProducer.Params(userWalletId) + return this.getSyncOrNull(params) + } } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetSingleCryptoCurrencyStatusUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetSingleCryptoCurrencyStatusUseCase.kt deleted file mode 100644 index 369303c3cb..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetSingleCryptoCurrencyStatusUseCase.kt +++ /dev/null @@ -1,106 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.currency.CryptoCurrencyStatus -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.tokens.error.CurrencyStatusError -import com.tangem.domain.tokens.error.mapper.mapToCurrencyError -import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations -import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.flow.* - -/** - * Use case for fetching the status of a cryptocurrency associated with a user wallet. - * - */ -class GetSingleCryptoCurrencyStatusUseCase( - private val currencyStatusOperations: BaseCurrencyStatusOperations, - private val dispatchers: CoroutineDispatcherProvider, -) { - - /** - * Returns cryptocurrency status flow for Multi-Currency wallet - * - * @param userWalletId The unique identifier of the user's wallet. - * @param currencyId The unique identifier of the cryptocurrency. - * @param isSingleWalletWithTokens Indicates whether the user wallet contains only one token on card (old cards) - * @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation. - */ - fun invokeMultiWallet( - userWalletId: UserWalletId, - currencyId: CryptoCurrency.ID, - isSingleWalletWithTokens: Boolean, - ): Flow> { - return flow { - emitAll( - getCurrencyStatus( - userWalletId = userWalletId, - currencyId = currencyId, - isSingleWalletWithTokens = isSingleWalletWithTokens, - ), - ) - }.flowOn(dispatchers.io) - } - - /** - * Returns cryptocurrency status flow for primary currency for Single-Currency wallet - * - * @param userWalletId The unique identifier of the user's wallet. - * @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation. - */ - fun invokeSingleWallet(userWalletId: UserWalletId): Flow> { - return flow { - emitAll( - currencyStatusOperations.getPrimaryCurrencyStatusFlow(userWalletId).map { maybeCurrency -> - maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError) - }, - ) - }.flowOn(dispatchers.io) - } - - /** - * Returns synchronously cryptocurrency status for Multi-Currency wallet - * - * @param userWalletId The unique identifier of the user's wallet. - * @param cryptoCurrencyId The unique identifier of the cryptocurrency. - * @param isSingleWalletWithTokens Indicates whether the user wallet contains only one token on card (old cards) - * @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation. - */ - suspend fun invokeMultiWalletSync( - userWalletId: UserWalletId, - cryptoCurrencyId: CryptoCurrency.ID, - isSingleWalletWithTokens: Boolean = false, - ): Either { - return currencyStatusOperations.getCurrencyStatusSync(userWalletId, cryptoCurrencyId, isSingleWalletWithTokens) - .mapLeft { error -> error.mapToCurrencyError() } - } - - /** - * Returns synchronously cryptocurrency status for primary currency for Single-Currency wallet - * - * @param userWalletId The unique identifier of the user's wallet. - * @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation. - */ - suspend fun invokeSingleWalletSync(userWalletId: UserWalletId): Either { - return currencyStatusOperations.getPrimaryCurrencyStatusSync(userWalletId) - .mapLeft { error -> error.mapToCurrencyError() } - } - - private suspend fun getCurrencyStatus( - userWalletId: UserWalletId, - currencyId: CryptoCurrency.ID, - isSingleWalletWithTokens: Boolean, - ): Flow> { - val currencyFlow = currencyStatusOperations.getCurrencyStatusFlow( - userWalletId = userWalletId, - currencyId = currencyId, - isSingleWalletWithTokens = isSingleWalletWithTokens, - ) - - return currencyFlow.map { maybeCurrency -> - maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError) - } - } -} \ No newline at end of file diff --git a/domain/transaction/build.gradle.kts b/domain/transaction/build.gradle.kts index 9bf72aeddb..aae9c5368c 100644 --- a/domain/transaction/build.gradle.kts +++ b/domain/transaction/build.gradle.kts @@ -26,6 +26,7 @@ dependencies { implementation(projects.libs.blockchainSdk) implementation(projects.libs.crypto) + implementation(projects.domain.account.status) implementation(projects.domain.models) implementation(projects.domain.legacy) implementation(projects.domain.walletManager) diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/gasless/CreateAndSendGaslessTransactionUseCase.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/gasless/CreateAndSendGaslessTransactionUseCase.kt index 6966933ca2..90b0f2d731 100644 --- a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/gasless/CreateAndSendGaslessTransactionUseCase.kt +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/gasless/CreateAndSendGaslessTransactionUseCase.kt @@ -1,6 +1,7 @@ package com.tangem.domain.transaction.usecase.gasless import arrow.core.Either +import arrow.core.getOrElse import arrow.core.raise.catch import arrow.core.raise.either import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras @@ -16,13 +17,13 @@ import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldS import com.tangem.common.CompletionResult import com.tangem.common.extensions.toDecompressedPublicKey import com.tangem.common.extensions.toHexString +import com.tangem.domain.account.status.utils.CryptoCurrencyOperations.getCryptoCurrency +import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.card.common.TapWorkarounds.isTangemTwins import com.tangem.domain.card.models.TwinKey import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.transaction.GaslessTransactionRepository import com.tangem.domain.transaction.error.SendTransactionError import com.tangem.domain.transaction.models.Eip7702Authorization @@ -33,7 +34,7 @@ import java.math.BigInteger class CreateAndSendGaslessTransactionUseCase( private val walletManagersFacade: WalletManagersFacade, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, + private val singleAccountListSupplier: SingleAccountListSupplier, private val gaslessTransactionRepository: GaslessTransactionRepository, private val cardSdkConfigRepository: CardSdkConfigRepository, private val getHotWalletSigner: (UserWallet.Hot) -> TransactionSigner, @@ -74,18 +75,17 @@ class CreateAndSendGaslessTransactionUseCase( transactionData: TransactionData.Uncompiled, fee: TransactionFeeExtended, ): GaslessContext { - val tokenForFeeStatus = getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync( - userWallet.walletId, - fee.feeTokenId, - ).getOrNull() ?: error("Token for fee not found") + val currency = singleAccountListSupplier.getSyncOrNull(userWalletId = userWallet.walletId) + .getCryptoCurrency(currencyId = fee.feeTokenId, network = null) + .getOrElse { error("Token for fee not found") } val walletManager = walletManagersFacade.getOrCreateWalletManager( userWallet.walletId, - tokenForFeeStatus.currency.network, - ) ?: error("WalletManager not found for network ${tokenForFeeStatus.currency.network.id}") + currency.network, + ) ?: error("WalletManager not found for network ${currency.network.id}") val gaslessDataProvider = walletManager as? EthereumGaslessDataProvider ?: error( - "WalletManager for network ${tokenForFeeStatus.currency.network.id} " + + "WalletManager for network ${currency.network.id} " + "does not support gasless transactions", ) @@ -94,16 +94,16 @@ class CreateAndSendGaslessTransactionUseCase( val gaslessTransactionData = createGaslessTransactionData( transactionData = transactionData, txFee = fee, - tokenFeeStatus = tokenForFeeStatus, + currency = currency, nonce = gaslessContractNonce, ) - val chainId = gaslessTransactionRepository.getChainIdForNetwork(tokenForFeeStatus.currency.network) + val chainId = gaslessTransactionRepository.getChainIdForNetwork(currency.network) return GaslessContext( walletManager = walletManager, gaslessDataProvider = gaslessDataProvider, - tokenForFeeStatus = tokenForFeeStatus, + currency = currency, gaslessTransactionData = gaslessTransactionData, chainId = chainId, ) @@ -189,7 +189,7 @@ class CreateAndSendGaslessTransactionUseCase( transactionData: TransactionData.Uncompiled, ): String { val txHash = gaslessTransactionRepository.signGaslessTransaction( - network = context.tokenForFeeStatus.currency.network, + network = context.currency.network, gaslessTransactionData = context.gaslessTransactionData, signature = signedData.eip712Signature, userAddress = transactionData.sourceAddress, @@ -244,11 +244,11 @@ class CreateAndSendGaslessTransactionUseCase( private suspend fun createGaslessTransactionData( transactionData: TransactionData.Uncompiled, txFee: TransactionFeeExtended, - tokenFeeStatus: CryptoCurrencyStatus, + currency: CryptoCurrency, nonce: BigInteger, ): GaslessTransactionData { val transaction = buildTransaction(transactionData) - val fee = buildFee(txFee, tokenFeeStatus) + val fee = buildFee(txFee, currency) return GaslessTransactionData( transaction = transaction, @@ -272,11 +272,8 @@ class CreateAndSendGaslessTransactionUseCase( ) } - private suspend fun buildFee( - txFee: TransactionFeeExtended, - tokenFeeStatus: CryptoCurrencyStatus, - ): GaslessTransactionData.Fee { - val tokenForFee = tokenFeeStatus.currency as? CryptoCurrency.Token + private suspend fun buildFee(txFee: TransactionFeeExtended, currency: CryptoCurrency): GaslessTransactionData.Fee { + val tokenForFee = currency as? CryptoCurrency.Token ?: error("Fee currency must be a token") val feeInTokenCurrency = txFee.transactionFee.normal as? Fee.Ethereum.TokenCurrency @@ -320,7 +317,7 @@ class CreateAndSendGaslessTransactionUseCase( private data class GaslessContext( val walletManager: WalletManager, val gaslessDataProvider: EthereumGaslessDataProvider, - val tokenForFeeStatus: CryptoCurrencyStatus, + val currency: CryptoCurrency, val gaslessTransactionData: GaslessTransactionData, val chainId: Int, ) diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt index ac73f11c28..836b3534d5 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt @@ -8,11 +8,12 @@ import arrow.core.raise.either import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier +import com.tangem.domain.account.status.utils.CryptoCurrencyStatusOperations.getCryptoCurrencyStatus import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.transaction.models.TransactionFeeExtended import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase @@ -55,7 +56,7 @@ internal class FeeSelectorLogic @AssistedInject constructor( private val feeSelectorCheckReloadTrigger: FeeSelectorCheckReloadTrigger, private val feeSelectorAlertFactory: FeeSelectorAlertFactory, private val analyticsEventHandler: AnalyticsEventHandler, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, private val getUserWalletUseCase: GetUserWalletUseCase, private val getAvailableFeeTokensUseCase: GetAvailableFeeTokensUseCase, isGaslessFeeSupportedForNetwork: IsGaslessFeeSupportedForNetwork, @@ -294,11 +295,9 @@ internal class FeeSelectorLogic @AssistedInject constructor( private suspend fun getSelectedTokenStatus(tokenId: CryptoCurrency.ID): Either = either { if (params.feeCryptoCurrencyStatus.currency.id != tokenId) { - getSingleCryptoCurrencyStatusUseCase - .invokeMultiWalletSync( - userWalletId = params.userWalletId, - cryptoCurrencyId = tokenId, - ).getOrElse { + singleAccountStatusListSupplier.getSyncOrNull(params.userWalletId) + .getCryptoCurrencyStatus(currencyId = tokenId, network = null) + .getOrElse { raise(GetFeeError.DataError(IllegalStateException("No token found for id: $tokenId"))) } } else { diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt index 4c90fa3f34..1d1951f503 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt @@ -35,7 +35,9 @@ import com.tangem.core.ui.utils.InputNumberFormatter import com.tangem.core.ui.utils.parseBigDecimal import com.tangem.datasource.local.appsflyer.AppsFlyerStore import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatus +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase +import com.tangem.domain.account.status.utils.CryptoCurrencyStatusOperations.getCryptoCurrencyStatus import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency @@ -69,7 +71,6 @@ import com.tangem.domain.tangempay.GetTangemPayCustomerIdUseCase import com.tangem.domain.tangempay.TangemPayWithdrawUseCase import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase import com.tangem.domain.tokens.GetMinimumTransactionAmountSyncUseCase -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.UpdateDelayedNetworkStatusUseCase import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.transaction.models.TransactionFeeExtended @@ -136,7 +137,6 @@ internal class SwapModel @Inject constructor( private val analyticsErrorEventHandler: AnalyticsErrorHandler, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val updateDelayedCurrencyStatusUseCase: UpdateDelayedNetworkStatusUseCase, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase, @@ -153,6 +153,7 @@ internal class SwapModel @Inject constructor( router: AppRouter, private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase, private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, private val getTangemPayCurrencyStatusUseCase: GetTangemPayCurrencyStatusUseCase, private val tangemPayWithdrawUseCase: TangemPayWithdrawUseCase, private val iGaslessFeeSupportedForNetwork: IsGaslessFeeSupportedForNetwork, @@ -386,10 +387,9 @@ internal class SwapModel @Inject constructor( } else { val fromStatus = getFromStatus() val toStatus = initialCurrencyTo?.let { currencyTo -> - getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync( - userWalletId = userWalletId, - cryptoCurrencyId = currencyTo.id, - ).getOrNull() + singleAccountStatusListSupplier.getSyncOrNull(params.userWalletId) + .getCryptoCurrencyStatus(currencyTo) + .getOrNull() } if (fromStatus == null) { @@ -2305,10 +2305,9 @@ internal class SwapModel @Inject constructor( depositAddress = tangemPayInput.depositAddress, ) } else { - getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync( - userWalletId = userWalletId, - cryptoCurrencyId = initialCurrencyFrom.id, - ).getOrNull() + singleAccountStatusListSupplier.getSyncOrNull(params.userWalletId) + .getCryptoCurrencyStatus(currency = initialCurrencyFrom) + .getOrNull() } } diff --git a/features/txhistory/impl/build.gradle.kts b/features/txhistory/impl/build.gradle.kts index c3b3021014..aae9596318 100644 --- a/features/txhistory/impl/build.gradle.kts +++ b/features/txhistory/impl/build.gradle.kts @@ -36,6 +36,7 @@ dependencies { implementation(projects.domain.tokens.models) implementation(projects.domain.balanceHiding) implementation(projects.domain.balanceHiding.models) + implementation(projects.domain.account.status) /* AndroidX */ implementation(deps.androidx.activity.compose) diff --git a/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/model/TxHistoryModel.kt b/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/model/TxHistoryModel.kt index d587d9b46c..7476b496da 100644 --- a/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/model/TxHistoryModel.kt +++ b/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/model/TxHistoryModel.kt @@ -1,22 +1,19 @@ package com.tangem.features.txhistory.model import androidx.compose.runtime.Stable -import arrow.core.Either +import arrow.core.Option import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.url.UrlOpener +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier +import com.tangem.domain.account.status.utils.CryptoCurrencyStatusOperations.getCryptoCurrencyStatus import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase -import com.tangem.domain.card.common.util.cardTypesResolver import com.tangem.domain.models.currency.CryptoCurrencyStatus -import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase -import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.txhistory.models.TxHistoryStateError import com.tangem.domain.txhistory.repository.TxHistoryRepositoryV2 import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase -import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.txhistory.component.TxHistoryComponent import com.tangem.features.txhistory.converter.TxHistoryItemToTransactionStateConverter import com.tangem.features.txhistory.entity.TxHistoryUM @@ -40,8 +37,7 @@ internal class TxHistoryModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, - private val getUserWalletUseCase: GetUserWalletUseCase, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, private val urlOpener: UrlOpener, private val txHistoryUpdateListener: TxHistoryUpdateListener, @@ -184,26 +180,20 @@ internal class TxHistoryModel @Inject constructor( } private fun subscribeOnCurrencyStatusUpdates() { - val userWallet: UserWallet = requireNotNull(getUserWalletUseCase(params.userWalletId).getOrNull()) { - "User wallet not found" - } - getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( - userWalletId = params.userWalletId, - currencyId = params.currency.id, - isSingleWalletWithTokens = userWallet is UserWallet.Cold && - userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(), - ) + singleAccountStatusListSupplier(params.userWalletId) + .map { it.getCryptoCurrencyStatus(currency = params.currency) } .distinctUntilChanged() .onEach(::handlePendingTxsChanges) - .flowOn(dispatchers.main) + .flowOn(dispatchers.default) .launchIn(modelScope) } - private fun handlePendingTxsChanges(maybeCurrencyStatus: Either) { - maybeCurrencyStatus.onRight { status -> + private fun handlePendingTxsChanges(maybeCurrencyStatus: Option) { + maybeCurrencyStatus.onSome { status -> val pendingTxs = status.value.pendingTransactions .map(txHistoryItemConverter::convert) .toPersistentList() + _uiState.update { state -> if (state is TxHistoryUM.NotSupported) { state.copy(pendingTransactions = pendingTxs) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt index 5c65edb11b..5c603a74b5 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt @@ -8,6 +8,7 @@ import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.ui.UiMessageSender +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.models.account.Account import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.currency.CryptoCurrency @@ -18,7 +19,6 @@ import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.nft.analytics.NFTAnalyticsEvent import com.tangem.domain.settings.ShouldShowMarketsTooltipUseCase import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.model.details.NavigationAction import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase @@ -94,7 +94,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( private val currencyActionsClickIntents: WalletCurrencyActionsClickIntentsImplementor, private val onrampStatusFactory: OnrampStatusFactory, private val getUserWalletUseCase: GetUserWalletUseCase, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, private val shouldShowMarketsTooltipUseCase: ShouldShowMarketsTooltipUseCase, @@ -269,7 +269,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( override fun onTransactionClick(txHash: String) { modelScope.launch(dispatchers.main) { - val currency = getSingleCryptoCurrencyStatusUseCase.unwrap( + val currency = singleAccountStatusListSupplier.unwrap( userWalletId = stateHolder.getSelectedWalletId(), ) ?.currency diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt index b57effd249..98811cfe6f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt @@ -22,6 +22,7 @@ import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.haptic.TangemHapticEffect import com.tangem.core.ui.haptic.VibratorHapticManager import com.tangem.core.ui.message.DialogMessage +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.extenstions.unwrap @@ -42,7 +43,10 @@ import com.tangem.domain.onramp.model.OnrampSource import com.tangem.domain.promo.GetStoryContentUseCase import com.tangem.domain.promo.models.StoryContentIds import com.tangem.domain.staking.model.StakingOption -import com.tangem.domain.tokens.* +import com.tangem.domain.tokens.IsCryptoCurrencyCoinCouldHideUseCase +import com.tangem.domain.tokens.NeedShowYieldSupplyDepositedWarningUseCase +import com.tangem.domain.tokens.SaveViewedTokenReceiveWarningUseCase +import com.tangem.domain.tokens.SaveViewedYieldSupplyWarningUseCase import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason import com.tangem.domain.tokens.model.analytics.TokenReceiveCopyActionSource import com.tangem.domain.tokens.model.analytics.TokenReceiveNewAnalyticsEvent @@ -124,7 +128,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val walletManagersFacade: WalletManagersFacade, private val isDemoCardUseCase: IsDemoCardUseCase, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, private val getExploreUrlUseCase: GetExploreUrlUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, @@ -485,7 +489,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( val userWalletId = stateHolder.getSelectedWalletId() modelScope.launch(dispatchers.main) { - val currencyStatus = getSingleCryptoCurrencyStatusUseCase.unwrap(userWalletId) ?: return@launch + val currencyStatus = singleAccountStatusListSupplier.unwrap(userWalletId) ?: return@launch when (val addresses = currencyStatus.value.networkAddress) { is NetworkAddress.Selectable -> { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/UseCaseExt.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/UseCaseExt.kt index 58da9fca4d..4b0d406ee5 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/UseCaseExt.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/UseCaseExt.kt @@ -1,13 +1,11 @@ package com.tangem.feature.wallet.presentation.wallet.domain -import arrow.core.Either +import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase -import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase -import kotlinx.coroutines.flow.* import timber.log.Timber internal fun GetSelectedWalletSyncUseCase.unwrap(): UserWallet? { @@ -20,29 +18,9 @@ internal fun GetSelectedWalletSyncUseCase.unwrap(): UserWallet? { ) } -internal suspend fun GetSingleCryptoCurrencyStatusUseCase.unwrap(userWalletId: UserWalletId): CryptoCurrencyStatus? { - return invokeSingleWallet(userWalletId) - .conflate() - .distinctUntilChanged() - .filter(Either::isRight) - .firstOrNull() - ?.fold( - ifLeft = { - Timber.e("Impossible to get primary currency status $it") - null - }, - ifRight = { it }, - ) -} - -internal suspend fun GetSingleCryptoCurrencyStatusUseCase.collectLatest( - userWalletId: UserWalletId, - onRight: suspend (CryptoCurrencyStatus) -> Unit, -) { - invokeSingleWallet(userWalletId = userWalletId) - .conflate() - .distinctUntilChanged() - .collectLatest { maybeStatus -> - maybeStatus.onRight { onRight(it) } - } +internal suspend fun SingleAccountStatusListSupplier.unwrap(userWalletId: UserWalletId): CryptoCurrencyStatus? { + return getSyncOrNull(params = SingleAccountStatusListProducer.Params(userWalletId)) + ?.mainAccount + ?.flattenCurrencies() + ?.firstOrNull() } \ No newline at end of file diff --git a/features/yield-supply/impl/build.gradle.kts b/features/yield-supply/impl/build.gradle.kts index f1b9082389..ada6f291fb 100644 --- a/features/yield-supply/impl/build.gradle.kts +++ b/features/yield-supply/impl/build.gradle.kts @@ -43,6 +43,7 @@ dependencies { implementation(projects.domain.models) implementation(projects.domain.appCurrency.models) implementation(projects.domain.appCurrency) + implementation(projects.domain.account.status) implementation(projects.domain.wallets.models) implementation(projects.domain.wallets) implementation(projects.domain.tokens.models) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/active/model/YieldSupplyActiveModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/active/model/YieldSupplyActiveModel.kt index 3c65576a24..8ddd253ffb 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/active/model/YieldSupplyActiveModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/active/model/YieldSupplyActiveModel.kt @@ -16,12 +16,13 @@ import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.format +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier +import com.tangem.domain.account.status.utils.CryptoCurrencyStatusOperations.getCryptoCurrencyStatus import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.domain.yield.supply.usecase.* import com.tangem.features.yield.supply.api.YieldSupplyActiveComponent @@ -55,7 +56,7 @@ internal class YieldSupplyActiveModel @Inject constructor( private val yieldSupplyGetMaxFeeUseCase: YieldSupplyGetMaxFeeUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, private val urlOpener: UrlOpener, private val appRouter: AppRouter, private val yieldSupplyGetDustMinAmountUseCase: YieldSupplyGetDustMinAmountUseCase, @@ -168,44 +169,44 @@ internal class YieldSupplyActiveModel @Inject constructor( ifRight = { wallet -> userWallet = wallet - getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( - userWalletId = params.userWalletId, - currencyId = cryptoCurrency.id, - isSingleWalletWithTokens = false, - ).onEach { maybeCryptoCurrency -> - maybeCryptoCurrency.fold( - ifRight = { cryptoCurrencyStatus -> - cryptoCurrencyStatusFlow.update { cryptoCurrencyStatus } + singleAccountStatusListSupplier(params.userWalletId) + .map { it.getCryptoCurrencyStatus(currency = cryptoCurrency) } + .distinctUntilChanged() + .onEach { maybeCryptoCurrency -> + maybeCryptoCurrency.fold( + ifSome = { cryptoCurrencyStatus -> + cryptoCurrencyStatusFlow.update { cryptoCurrencyStatus } - val protocolBalance = - cryptoCurrencyStatus.value.yieldSupplyStatus?.effectiveProtocolBalance - ?: yieldSupplyGetProtocolBalanceUseCase( - userWalletId = userWalletId, - cryptoCurrency = cryptoCurrency, - ).getOrNull() + val protocolBalance = + cryptoCurrencyStatus.value.yieldSupplyStatus?.effectiveProtocolBalance + ?: yieldSupplyGetProtocolBalanceUseCase( + userWalletId = userWalletId, + cryptoCurrency = cryptoCurrency, + ).getOrNull() - loadApy() - loadMinAmount() - loadFees() + loadApy() + loadMinAmount() + loadFees() - uiState.update { - it.copy( - availableBalance = stringReference( - protocolBalance.format { - crypto( - symbol = AAVEV3_PREFIX + cryptoCurrency.symbol, - decimals = cryptoCurrency.decimals, - ) - }, - ), - ) - } - }, - ifLeft = { - Timber.w(it.toString()) - }, - ) - }.flowOn(dispatchers.default) + uiState.update { + it.copy( + availableBalance = stringReference( + protocolBalance.format { + crypto( + symbol = AAVEV3_PREFIX + cryptoCurrency.symbol, + decimals = cryptoCurrency.decimals, + ) + }, + ), + ) + } + }, + ifEmpty = { + Timber.w("No currency status found: ${cryptoCurrency.id}") + }, + ) + } + .flowOn(dispatchers.default) .launchIn(modelScope) }, ifLeft = { error -> diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/entry/model/YieldSupplyEntryModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/entry/model/YieldSupplyEntryModel.kt index 90a25adf75..5314191db2 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/entry/model/YieldSupplyEntryModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/entry/model/YieldSupplyEntryModel.kt @@ -5,9 +5,10 @@ import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier +import com.tangem.domain.account.status.utils.CryptoCurrencyStatusOperations.getCryptoCurrencyStatus import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.model.details.NavigationAction import com.tangem.domain.yield.supply.usecase.YieldSupplyEnterStatusUseCase import com.tangem.features.yield.supply.api.YieldSupplyEntryComponent @@ -24,7 +25,7 @@ internal class YieldSupplyEntryModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val router: Router, private val yieldSupplyEnterStatusUseCase: YieldSupplyEnterStatusUseCase, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, ) : Model() { private val params = paramsContainer.require() @@ -39,22 +40,22 @@ internal class YieldSupplyEntryModel @Inject constructor( val userWalletId = params.userWalletId val cryptoCurrency = params.cryptoCurrency modelScope.launch(dispatchers.default) { - getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync( - userWalletId = userWalletId, - cryptoCurrencyId = cryptoCurrency.id, - ).onLeft { error -> - Timber.e("Failed to get CryptoCurrencyStatus: $error") - withContext(dispatchers.mainImmediate) { - router.pop() - } - }.onRight { cryptoCurrencyStatus -> - withContext(dispatchers.mainImmediate) { - val route = getInitialRoute(cryptoCurrencyStatus) - if (route != null) { - router.replaceCurrent(route) + singleAccountStatusListSupplier.getSyncOrNull(userWalletId) + .getCryptoCurrencyStatus(currency = cryptoCurrency) + .onNone { + Timber.e("Failed to get CryptoCurrencyStatus: ${cryptoCurrency.id}") + withContext(dispatchers.mainImmediate) { + router.pop() + } + } + .onSome { cryptoCurrencyStatus -> + withContext(dispatchers.mainImmediate) { + val route = getInitialRoute(cryptoCurrencyStatus) + if (route != null) { + router.replaceCurrent(route) + } } } - } } } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt index 381a2c9fab..ac026fed7c 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt @@ -11,6 +11,8 @@ import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.combinedReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier +import com.tangem.domain.account.status.utils.CryptoCurrencyStatusOperations.getCryptoCurrencyStatus import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.StatusSource @@ -21,7 +23,6 @@ import com.tangem.domain.models.currency.shouldShowNotSuppliedNotification import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.yield.supply.YieldSupplyStatus import com.tangem.domain.networks.single.SingleNetworkStatusFetcher -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.domain.yield.supply.models.YieldSupplyPendingStatus import com.tangem.domain.yield.supply.usecase.* @@ -35,9 +36,9 @@ import com.tangem.utils.transformer.update import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import timber.log.Timber +import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject import kotlin.properties.Delegates -import java.util.concurrent.atomic.AtomicBoolean @Suppress("LongParameterList", "LargeClass") @ModelScoped @@ -48,7 +49,7 @@ internal class YieldSupplyModel @Inject constructor( private val appRouter: AppRouter, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher, private val yieldSupplyGetTokenStatusUseCase: YieldSupplyGetTokenStatusUseCase, private val yieldSupplyIsAvailableUseCase: YieldSupplyIsAvailableUseCase, @@ -109,32 +110,33 @@ internal class YieldSupplyModel @Inject constructor( private fun subscribeOnCurrencyStatusUpdates() { combine( - getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( - userWalletId = params.userWalletId, - currencyId = cryptoCurrency.id, - isSingleWalletWithTokens = false, - ), - yieldSupplyEnterStatusFlowUseCase( + flow = singleAccountStatusListSupplier(params.userWalletId).map { + it.getCryptoCurrencyStatus(currency = cryptoCurrency) + }, + flow2 = yieldSupplyEnterStatusFlowUseCase( userWalletId = params.userWalletId, cryptoCurrency = cryptoCurrency, ), ) { maybeCryptoCurrency, _ -> maybeCryptoCurrency - }.flowOn(dispatchers.io) + } + .flowOn(dispatchers.io) + .distinctUntilChanged() .onEach { maybeCryptoCurrency -> maybeCryptoCurrency.fold( - ifRight = { cryptoCurrencyStatus -> + ifSome = { cryptoCurrencyStatus -> latestCryptoCurrencyStatus = cryptoCurrencyStatus if (isFirstCryptoCurrencyStatusEmission.compareAndSet(true, false)) { sendInfoAboutProtocolStatus(cryptoCurrencyStatus) } onCryptoCurrencyStatusUpdated(cryptoCurrencyStatus) }, - ifLeft = { - Timber.w(it.toString()) + ifEmpty = { + Timber.w("Unable to get crypto currency status: ${cryptoCurrency.id}") }, ) - }.launchIn(modelScope) + } + .launchIn(modelScope) } private suspend fun loadTokenStatus() { diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt index 9c8635a26b..f66d505e7f 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt @@ -13,13 +13,14 @@ import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIco import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.datasource.local.appsflyer.AppsFlyerStore +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier +import com.tangem.domain.account.status.utils.CryptoCurrencyStatusOperations.getCryptoCurrencyStatus import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.isHotWallet import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.transaction.usecase.SendTransactionUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase @@ -55,7 +56,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( paramsContainer: ParamsContainer, private val analytics: AnalyticsEventHandler, private val getUserWalletUseCase: GetUserWalletUseCase, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val sendTransactionUseCase: SendTransactionUseCase, private val yieldSupplyStartEarningUseCase: YieldSupplyStartEarningUseCase, @@ -346,27 +347,27 @@ internal class YieldSupplyStartEarningModel @Inject constructor( } private fun getCurrenciesStatusUpdates() { - getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( - userWalletId = userWalletId, - currencyId = cryptoCurrency.id, - isSingleWalletWithTokens = false, - ).onEach { maybeCryptoCurrency -> - maybeCryptoCurrency.fold( - ifRight = { cryptoCurrencyStatus -> - onDataLoaded( - currencyStatus = cryptoCurrencyStatus, - feeCurrencyStatus = getFeePaidCryptoCurrencyStatusSyncUseCase( - userWalletId = userWalletId, - cryptoCurrencyStatus = cryptoCurrencyStatus, - ).getOrNull() ?: cryptoCurrencyStatus, - ) - }, - ifLeft = { - Timber.w(it.toString()) - showAlertError() - }, - ) - }.launchIn(modelScope) + singleAccountStatusListSupplier(params.userWalletId) + .map { it.getCryptoCurrencyStatus(currency = cryptoCurrency) } + .distinctUntilChanged() + .onEach { maybeCryptoCurrency -> + maybeCryptoCurrency.fold( + ifSome = { cryptoCurrencyStatus -> + onDataLoaded( + currencyStatus = cryptoCurrencyStatus, + feeCurrencyStatus = getFeePaidCryptoCurrencyStatusSyncUseCase( + userWalletId = userWalletId, + cryptoCurrencyStatus = cryptoCurrencyStatus, + ).getOrNull() ?: cryptoCurrencyStatus, + ) + }, + ifEmpty = { + Timber.w("Unable to get crypto currency status: ${cryptoCurrency.id}") + showAlertError() + }, + ) + } + .launchIn(modelScope) } private fun onDataLoaded(currencyStatus: CryptoCurrencyStatus, feeCurrencyStatus: CryptoCurrencyStatus) {