Updated on 2026-08-14
This commit is contained in:
parent
91d8932543
commit
b37227d533
9 changed files with 144 additions and 40 deletions
|
|
@ -92,4 +92,12 @@ internal object CardDomainModule {
|
|||
fun provideNetworkHasDerivationUseCase(): NetworkHasDerivationUseCase {
|
||||
return NetworkHasDerivationUseCase()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideIsRequiredDerivePublicKeysUseCase(
|
||||
derivationsRepository: DerivationsRepository,
|
||||
): HasMissedDerivationsUseCase {
|
||||
return HasMissedDerivationsUseCase(derivationsRepository)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.domain.card
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.card.EllipticCurve
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
|
|
@ -8,8 +10,10 @@ import com.tangem.common.doOnSuccess
|
|||
import com.tangem.common.extensions.ByteArrayKey
|
||||
import com.tangem.common.extensions.toMapKey
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
import com.tangem.data.common.currency.getNetwork
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.card.repository.DerivationsRepository
|
||||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
|
|
@ -52,6 +56,26 @@ internal class DefaultDerivationsRepository(
|
|||
derivePublicKeys(userWalletId = userWalletId, derivations = derivations)
|
||||
}
|
||||
|
||||
override suspend fun hasMissedDerivations(
|
||||
userWalletId: UserWalletId,
|
||||
networksWithDerivationPath: Map<Network.ID, String?>,
|
||||
): Boolean {
|
||||
val userWallet = userWalletsStore.getSyncOrNull(userWalletId) ?: error("User wallet not found")
|
||||
|
||||
val derivations = MissedDerivationsFinder(scanResponse = userWallet.scanResponse)
|
||||
.findByNetworks(
|
||||
networksWithDerivationPath.mapNotNull { (networkId, extraDerivationPath) ->
|
||||
getNetwork(
|
||||
blockchain = Blockchain.fromNetworkId(networkId.value) ?: return@mapNotNull null,
|
||||
extraDerivationPath = extraDerivationPath,
|
||||
derivationStyleProvider = userWallet.scanResponse.derivationStyleProvider,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
return derivations.isNotEmpty()
|
||||
}
|
||||
|
||||
override suspend fun derivePublicKeys(userWalletId: UserWalletId, derivations: Derivations): DerivedKeys {
|
||||
tangemSdkManager.derivePublicKeys(cardId = null, derivations = derivations)
|
||||
.doOnSuccess { response ->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.domain.card
|
||||
|
||||
import com.tangem.domain.card.repository.DerivationsRepository
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
/**
|
||||
* Use case to check if user has missed derivations
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class HasMissedDerivationsUseCase(
|
||||
private val derivationsRepository: DerivationsRepository,
|
||||
) {
|
||||
|
||||
/** Check if user [userWalletId] has missed derivations using map of [Network.ID] with extraDerivationPath */
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
networksWithDerivationPath: Map<Network.ID, String?>,
|
||||
): Boolean {
|
||||
return derivationsRepository.hasMissedDerivations(userWalletId, networksWithDerivationPath)
|
||||
}
|
||||
}
|
||||
|
|
@ -20,4 +20,10 @@ interface DerivationsRepository {
|
|||
userWalletId: UserWalletId,
|
||||
derivations: Map<ByteArrayKey, List<DerivationPath>>,
|
||||
): Map<ByteArrayKey, ExtendedPublicKeysMap>
|
||||
|
||||
/** Check if user [userWalletId] has missed derivations using map of [Network.ID] with extraDerivationPath */
|
||||
suspend fun hasMissedDerivations(
|
||||
userWalletId: UserWalletId,
|
||||
networksWithDerivationPath: Map<Network.ID, String?>,
|
||||
): Boolean
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ dependencies {
|
|||
implementation(projects.domain.appCurrency.models)
|
||||
implementation(projects.domain.balanceHiding)
|
||||
implementation(projects.domain.balanceHiding.models)
|
||||
implementation(projects.domain.card)
|
||||
implementation(projects.domain.markets)
|
||||
implementation(projects.domain.staking.models)
|
||||
implementation(projects.domain.tokens)
|
||||
|
|
|
|||
|
|
@ -36,21 +36,21 @@ internal class AddToPortfolioBSContentUMFactory(
|
|||
/**
|
||||
* Create [TangemBottomSheetConfig]
|
||||
*
|
||||
* @param portfolioData portfolio data
|
||||
* @param portfolioBSVisibilityModel portfolio bottom sheet visibility model
|
||||
* @param selectedWallet selected wallet
|
||||
* @param networksWithToggle networks with toggle
|
||||
* @param isUserChangedNetworks flag indicates if user changed networks
|
||||
* @param portfolioData portfolio data
|
||||
* @param portfolioUIData portfolio bottom sheet visibility model
|
||||
* @param selectedWallet selected wallet
|
||||
* @param networksWithToggle networks with toggle
|
||||
* @param isUserChangedNetworks flag indicates if user changed networks
|
||||
*/
|
||||
fun create(
|
||||
portfolioData: PortfolioData,
|
||||
portfolioBSVisibilityModel: PortfolioBSVisibilityModel,
|
||||
portfolioUIData: PortfolioUIData,
|
||||
selectedWallet: UserWallet,
|
||||
networksWithToggle: Map<TokenMarketInfo.Network, Boolean>,
|
||||
isUserChangedNetworks: Boolean,
|
||||
): TangemBottomSheetConfig {
|
||||
return TangemBottomSheetConfig(
|
||||
isShow = portfolioBSVisibilityModel.addToPortfolioBSVisibility,
|
||||
isShow = portfolioUIData.portfolioBSVisibilityModel.addToPortfolioBSVisibility,
|
||||
onDismissRequest = { onAddToPortfolioVisibilityChange(false) },
|
||||
content = AddToPortfolioBSContentUM(
|
||||
selectedWallet = selectedWallet.toSelectedUserWalletItemUM(),
|
||||
|
|
@ -58,11 +58,11 @@ internal class AddToPortfolioBSContentUMFactory(
|
|||
networksWithToggle = networksWithToggle,
|
||||
onNetworkSwitchClick = onNetworkSwitchClick,
|
||||
).convert(value = token),
|
||||
isScanCardNotificationVisible = false, // TODO [REDACTED_JIRA]
|
||||
isScanCardNotificationVisible = portfolioUIData.hasMissedDerivations,
|
||||
continueButtonEnabled = isUserChangedNetworks,
|
||||
onContinueButtonClick = onContinueClick,
|
||||
walletSelectorConfig = crateWalletSelectorBSConfig(
|
||||
isShow = portfolioBSVisibilityModel.walletSelectorBSVisibility,
|
||||
isShow = portfolioUIData.portfolioBSVisibilityModel.walletSelectorBSVisibility,
|
||||
portfolioData = portfolioData,
|
||||
selectedWalletId = selectedWallet.walletId,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ import arrow.core.getOrElse
|
|||
import com.tangem.core.decompose.di.ComponentScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.domain.card.HasMissedDerivationsUseCase
|
||||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.features.markets.portfolio.api.MarketsPortfolioComponent
|
||||
|
|
@ -24,6 +26,7 @@ internal class MarketsPortfolioModel @Inject constructor(
|
|||
paramsContainer: ParamsContainer,
|
||||
private val getSelectedWalletUseCase: GetSelectedWalletUseCase,
|
||||
private val portfolioDataLoader: PortfolioDataLoader,
|
||||
private val hasMissedDerivationsUseCase: HasMissedDerivationsUseCase,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -85,16 +88,45 @@ internal class MarketsPortfolioModel @Inject constructor(
|
|||
private fun subscribeOnStateUpdates() {
|
||||
combine(
|
||||
flow = portfolioDataLoader.load(params.token.id),
|
||||
flow2 = portfolioBSVisibilityModelFlow,
|
||||
flow2 = getPortfolioUIDataFlow(),
|
||||
flow3 = availableNetworksFlow,
|
||||
flow4 = selectedMultiWalletIdFlow,
|
||||
flow5 = walletsWithChangedNetworksFlow,
|
||||
transform = factory::create,
|
||||
)
|
||||
.onEach { _state.value = it }
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun getPortfolioUIDataFlow(): Flow<PortfolioUIData> {
|
||||
return combine(
|
||||
flow = portfolioBSVisibilityModelFlow,
|
||||
flow2 = selectedMultiWalletIdFlow,
|
||||
flow3 = walletsWithChangedNetworksFlow,
|
||||
transform = { portfolioBSVisibilityModel, selectedWalletId, walletsWithChangedNetworks ->
|
||||
PortfolioUIData(
|
||||
portfolioBSVisibilityModel = portfolioBSVisibilityModel,
|
||||
selectedWalletId = selectedWalletId,
|
||||
walletsWithChangedNetworks = walletsWithChangedNetworks,
|
||||
hasMissedDerivations = hasMissedDerivations(selectedWalletId, walletsWithChangedNetworks),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun hasMissedDerivations(
|
||||
selectedWalletId: UserWalletId?,
|
||||
walletsWithChangedNetworks: Map<UserWalletId, List<String>>,
|
||||
): Boolean {
|
||||
return if (selectedWalletId != null) {
|
||||
hasMissedDerivationsUseCase.invoke(
|
||||
userWalletId = selectedWalletId,
|
||||
networksWithDerivationPath = walletsWithChangedNetworks[selectedWalletId].orEmpty()
|
||||
.associate { Network.ID(it) to null },
|
||||
)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun onTokenItemClick(index: Int, id: CryptoCurrency.ID) {
|
||||
_state.update {
|
||||
val state = _state.value as? MyPortfolioUM.Tokens ?: return@update it
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.tangem.domain.markets.TokenMarketInfo
|
|||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.markets.portfolio.impl.loader.PortfolioData
|
||||
import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM
|
||||
|
||||
|
|
@ -24,17 +23,15 @@ internal class MyPortfolioUMMFactory(
|
|||
) {
|
||||
|
||||
fun create(
|
||||
portfolioModel: PortfolioData,
|
||||
portfolioBSVisibilityModel: PortfolioBSVisibilityModel,
|
||||
portfolioData: PortfolioData,
|
||||
portfolioUIData: PortfolioUIData,
|
||||
availableNetworks: List<TokenMarketInfo.Network>?,
|
||||
selectedWalletId: UserWalletId?,
|
||||
walletsWithChangedNetworks: Map<UserWalletId, List<String>>,
|
||||
): MyPortfolioUM {
|
||||
if (availableNetworks == null) return MyPortfolioUM.Loading
|
||||
|
||||
if (availableNetworks.isEmpty()) return MyPortfolioUM.Unavailable
|
||||
|
||||
val walletsWithStatuses = portfolioModel.walletsWithCurrencyStatuses
|
||||
val walletsWithStatuses = portfolioData.walletsWithCurrencyStatuses
|
||||
.filterAvailableNetworks(networks = availableNetworks)
|
||||
|
||||
val isPortfolioEmpty = walletsWithStatuses.flatMap { it.value }.isEmpty()
|
||||
|
|
@ -44,11 +41,9 @@ internal class MyPortfolioUMMFactory(
|
|||
return if (hasMultiWallets) {
|
||||
MyPortfolioUM.AddFirstToken(
|
||||
bsConfig = createAddToPortfolioBSConfig(
|
||||
portfolioModel = portfolioModel,
|
||||
selectedWalletId = selectedWalletId,
|
||||
portfolioData = portfolioData,
|
||||
portfolioUIData = portfolioUIData,
|
||||
availableNetworks = availableNetworks,
|
||||
walletsWithChangedNetworks = walletsWithChangedNetworks,
|
||||
portfolioBSVisibilityModel = portfolioBSVisibilityModel,
|
||||
),
|
||||
onAddClick = onAddClick,
|
||||
)
|
||||
|
|
@ -58,15 +53,13 @@ internal class MyPortfolioUMMFactory(
|
|||
}
|
||||
|
||||
return TokensPortfolioUMConverter(
|
||||
appCurrency = portfolioModel.appCurrency,
|
||||
isBalanceHidden = portfolioModel.isBalanceHidden,
|
||||
appCurrency = portfolioData.appCurrency,
|
||||
isBalanceHidden = portfolioData.isBalanceHidden,
|
||||
isAllAvailableNetworksAdded = walletsWithStatuses.isAllAvailableNetworksAdded(availableNetworks),
|
||||
bsConfig = createAddToPortfolioBSConfig(
|
||||
portfolioModel = portfolioModel,
|
||||
selectedWalletId = selectedWalletId,
|
||||
portfolioData = portfolioData,
|
||||
portfolioUIData = portfolioUIData,
|
||||
availableNetworks = availableNetworks,
|
||||
portfolioBSVisibilityModel = portfolioBSVisibilityModel,
|
||||
walletsWithChangedNetworks = walletsWithChangedNetworks,
|
||||
),
|
||||
onAddClick = onAddClick,
|
||||
onTokenItemClick = onTokenItemClick,
|
||||
|
|
@ -75,23 +68,20 @@ internal class MyPortfolioUMMFactory(
|
|||
}
|
||||
|
||||
private fun createAddToPortfolioBSConfig(
|
||||
portfolioModel: PortfolioData,
|
||||
selectedWalletId: UserWalletId?,
|
||||
portfolioData: PortfolioData,
|
||||
portfolioUIData: PortfolioUIData,
|
||||
availableNetworks: List<TokenMarketInfo.Network>,
|
||||
portfolioBSVisibilityModel: PortfolioBSVisibilityModel,
|
||||
walletsWithChangedNetworks: Map<UserWalletId, List<String>>,
|
||||
): TangemBottomSheetConfig {
|
||||
val walletId = requireNotNull(selectedWalletId) {
|
||||
"Selected wallet must be not null in state with AddToPortfolio bottom sheet"
|
||||
}
|
||||
val walletId = portfolioUIData.selectedWalletId
|
||||
?: portfolioData.walletsWithCurrencyStatuses.keys.firstOrNull { it.isMultiCurrency }?.walletId
|
||||
|
||||
val selectedWallet = portfolioModel.walletsWithCurrencyStatuses.keys
|
||||
val selectedWallet = portfolioData.walletsWithCurrencyStatuses.keys
|
||||
.firstOrNull { it.walletId == walletId }
|
||||
?: error("portfolioModel.walletsWithCurrencyStatuses doesn't contain selected wallet: $walletId")
|
||||
|
||||
val changedNetworks = walletsWithChangedNetworks[selectedWalletId]
|
||||
val changedNetworks = portfolioUIData.walletsWithChangedNetworks[portfolioUIData.selectedWalletId]
|
||||
val alreadyAddedNetworks = requireNotNull(
|
||||
value = portfolioModel.walletsWithCurrencyStatuses[selectedWallet],
|
||||
value = portfolioData.walletsWithCurrencyStatuses[selectedWallet],
|
||||
lazyMessage = {
|
||||
"portfolioModel.walletsWithCurrencyStatuses doesn't contain selected wallet: $walletId"
|
||||
},
|
||||
|
|
@ -100,8 +90,8 @@ internal class MyPortfolioUMMFactory(
|
|||
.map { it.currency.network.backendId }
|
||||
|
||||
return addToPortfolioBSContentUMFactory.create(
|
||||
portfolioData = portfolioModel,
|
||||
portfolioBSVisibilityModel = portfolioBSVisibilityModel,
|
||||
portfolioData = portfolioData,
|
||||
portfolioUIData = portfolioUIData,
|
||||
selectedWallet = selectedWallet,
|
||||
networksWithToggle = availableNetworks.associateWithToggle(
|
||||
changedNetworks = changedNetworks,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.features.markets.portfolio.impl.model
|
||||
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
/**
|
||||
* Portfolio UI data. Combined data from all UI flows that required to setup portfolio
|
||||
*
|
||||
* @property portfolioBSVisibilityModel portfolio bottom sheet visibility model
|
||||
* @property selectedWalletId selected wallet id
|
||||
* @property walletsWithChangedNetworks wallets with changed networks
|
||||
* @property hasMissedDerivations flag that indicates if user has missed derivations
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal data class PortfolioUIData(
|
||||
val portfolioBSVisibilityModel: PortfolioBSVisibilityModel,
|
||||
val selectedWalletId: UserWalletId?,
|
||||
val walletsWithChangedNetworks: Map<UserWalletId, List<String>>,
|
||||
val hasMissedDerivations: Boolean,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue