Updated on 2026-08-14
This commit is contained in:
commit
ec7dcde2d3
5 changed files with 79 additions and 11 deletions
|
|
@ -84,4 +84,10 @@ internal object CardDomainModule {
|
||||||
fun provideResetCardUseCase(tangemSdkManager: TangemSdkManager): ResetCardUseCase {
|
fun provideResetCardUseCase(tangemSdkManager: TangemSdkManager): ResetCardUseCase {
|
||||||
return DefaultResetCardUseCase(tangemSdkManager)
|
return DefaultResetCardUseCase(tangemSdkManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideNetworkHasDerivationUseCase(): NetworkHasDerivationUseCase {
|
||||||
|
return NetworkHasDerivationUseCase()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.tangem.domain.card
|
||||||
|
|
||||||
|
import arrow.core.Either
|
||||||
|
import com.tangem.blockchain.common.Blockchain
|
||||||
|
import com.tangem.domain.common.util.hasDerivation
|
||||||
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
import com.tangem.domain.tokens.model.Network
|
||||||
|
|
||||||
|
class NetworkHasDerivationUseCase {
|
||||||
|
|
||||||
|
operator fun invoke(scanResponse: ScanResponse, network: Network): Either<Throwable, Boolean> {
|
||||||
|
val blockchain = Blockchain.fromId(network.id.value)
|
||||||
|
val derivationPath = network.derivationPath.value
|
||||||
|
return Either.catch { derivationPath != null && scanResponse.hasDerivation(blockchain, derivationPath) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory
|
package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory
|
||||||
|
|
||||||
|
import arrow.core.getOrElse
|
||||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||||
import com.tangem.core.ui.event.consumedEvent
|
import com.tangem.core.ui.event.consumedEvent
|
||||||
|
|
@ -7,8 +8,11 @@ import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.core.ui.extensions.networkIconResId
|
import com.tangem.core.ui.extensions.networkIconResId
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
|
import com.tangem.domain.card.NetworkHasDerivationUseCase
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||||
import com.tangem.domain.tokens.model.Network
|
import com.tangem.domain.tokens.model.Network
|
||||||
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
|
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.*
|
import com.tangem.feature.tokendetails.presentation.tokendetails.state.*
|
||||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton
|
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton
|
||||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsPullToRefreshConfig
|
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsPullToRefreshConfig
|
||||||
|
|
@ -25,6 +29,9 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
internal class TokenDetailsSkeletonStateConverter(
|
internal class TokenDetailsSkeletonStateConverter(
|
||||||
private val clickIntents: TokenDetailsClickIntents,
|
private val clickIntents: TokenDetailsClickIntents,
|
||||||
private val featureToggles: TokenDetailsFeatureToggles,
|
private val featureToggles: TokenDetailsFeatureToggles,
|
||||||
|
private val networkHasDerivationUseCase: NetworkHasDerivationUseCase,
|
||||||
|
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||||
|
private val userWalletId: UserWalletId,
|
||||||
) : Converter<CryptoCurrency, TokenDetailsState> {
|
) : Converter<CryptoCurrency, TokenDetailsState> {
|
||||||
|
|
||||||
private val iconStateConverter by lazy { TokenDetailsIconStateConverter() }
|
private val iconStateConverter by lazy { TokenDetailsIconStateConverter() }
|
||||||
|
|
@ -78,13 +85,7 @@ internal class TokenDetailsSkeletonStateConverter(
|
||||||
|
|
||||||
private fun createMenu(cryptoCurrency: CryptoCurrency): TokenDetailsAppBarMenuConfig = TokenDetailsAppBarMenuConfig(
|
private fun createMenu(cryptoCurrency: CryptoCurrency): TokenDetailsAppBarMenuConfig = TokenDetailsAppBarMenuConfig(
|
||||||
items = buildList {
|
items = buildList {
|
||||||
if (featureToggles.isGenerateXPubEnabled() && isBitcoin(cryptoCurrency.network.id.value)) {
|
addGenerateXPubMenuItem(cryptoCurrency)
|
||||||
TokenDetailsAppBarMenuConfig.MenuItem(
|
|
||||||
title = resourceReference(R.string.token_details_generate_xpub),
|
|
||||||
textColorProvider = { TangemTheme.colors.text.primary1 },
|
|
||||||
onClick = clickIntents::onGenerateExtendedKey,
|
|
||||||
).let(::add)
|
|
||||||
}
|
|
||||||
TokenDetailsAppBarMenuConfig.MenuItem(
|
TokenDetailsAppBarMenuConfig.MenuItem(
|
||||||
title = TextReference.Res(id = R.string.token_details_hide_token),
|
title = TextReference.Res(id = R.string.token_details_hide_token),
|
||||||
textColorProvider = { TangemTheme.colors.text.warning },
|
textColorProvider = { TangemTheme.colors.text.warning },
|
||||||
|
|
@ -93,6 +94,26 @@ internal class TokenDetailsSkeletonStateConverter(
|
||||||
}.toImmutableList(),
|
}.toImmutableList(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private fun MutableList<TokenDetailsAppBarMenuConfig.MenuItem>.addGenerateXPubMenuItem(
|
||||||
|
cryptoCurrency: CryptoCurrency,
|
||||||
|
) {
|
||||||
|
val userWallet = getUserWalletUseCase(userWalletId).getOrNull() ?: return
|
||||||
|
val isGenerateXPubEnabled = featureToggles.isGenerateXPubEnabled()
|
||||||
|
val isBitcoin = isBitcoin(cryptoCurrency.network.id.value)
|
||||||
|
val hasDerivations =
|
||||||
|
networkHasDerivationUseCase(userWallet.scanResponse, cryptoCurrency.network).getOrElse { false }
|
||||||
|
|
||||||
|
if (isGenerateXPubEnabled && isBitcoin && hasDerivations) {
|
||||||
|
add(
|
||||||
|
TokenDetailsAppBarMenuConfig.MenuItem(
|
||||||
|
title = resourceReference(R.string.token_details_generate_xpub),
|
||||||
|
textColorProvider = { TangemTheme.colors.text.primary1 },
|
||||||
|
onClick = clickIntents::onGenerateExtendedKey,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createButtons(): ImmutableList<TokenDetailsActionButton> {
|
private fun createButtons(): ImmutableList<TokenDetailsActionButton> {
|
||||||
return persistentListOf(
|
return persistentListOf(
|
||||||
TokenDetailsActionButton.Buy(dimContent = false, onClick = {}),
|
TokenDetailsActionButton.Buy(dimContent = false, onClick = {}),
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.wrappedList
|
import com.tangem.core.ui.extensions.wrappedList
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
|
import com.tangem.domain.card.NetworkHasDerivationUseCase
|
||||||
import com.tangem.domain.common.CardTypesResolver
|
import com.tangem.domain.common.CardTypesResolver
|
||||||
import com.tangem.domain.staking.model.StakingAvailability
|
import com.tangem.domain.staking.model.StakingAvailability
|
||||||
import com.tangem.domain.staking.model.StakingEntryInfo
|
import com.tangem.domain.staking.model.StakingEntryInfo
|
||||||
|
|
@ -24,6 +25,11 @@ import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
|
||||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||||
import com.tangem.domain.txhistory.models.TxHistoryListError
|
import com.tangem.domain.txhistory.models.TxHistoryListError
|
||||||
import com.tangem.domain.txhistory.models.TxHistoryStateError
|
import com.tangem.domain.txhistory.models.TxHistoryStateError
|
||||||
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
|
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||||
|
import com.tangem.feature.tokendetails.presentation.tokendetails.state.SwapTransactionsState
|
||||||
|
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsAppBarMenuConfig
|
||||||
|
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
|
||||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.*
|
import com.tangem.feature.tokendetails.presentation.tokendetails.state.*
|
||||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsDialogConfig
|
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsDialogConfig
|
||||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadedTxHistoryConverter
|
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadedTxHistoryConverter
|
||||||
|
|
@ -46,6 +52,9 @@ internal class TokenDetailsStateFactory(
|
||||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus?>,
|
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus?>,
|
||||||
private val clickIntents: TokenDetailsClickIntents,
|
private val clickIntents: TokenDetailsClickIntents,
|
||||||
private val featureToggles: TokenDetailsFeatureToggles,
|
private val featureToggles: TokenDetailsFeatureToggles,
|
||||||
|
private val networkHasDerivationUseCase: NetworkHasDerivationUseCase,
|
||||||
|
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||||
|
private val userWalletId: UserWalletId,
|
||||||
stakingFeatureToggles: StakingFeatureToggles,
|
stakingFeatureToggles: StakingFeatureToggles,
|
||||||
symbol: String,
|
symbol: String,
|
||||||
decimals: Int,
|
decimals: Int,
|
||||||
|
|
@ -55,6 +64,9 @@ internal class TokenDetailsStateFactory(
|
||||||
TokenDetailsSkeletonStateConverter(
|
TokenDetailsSkeletonStateConverter(
|
||||||
clickIntents = clickIntents,
|
clickIntents = clickIntents,
|
||||||
featureToggles = featureToggles,
|
featureToggles = featureToggles,
|
||||||
|
networkHasDerivationUseCase = networkHasDerivationUseCase,
|
||||||
|
getUserWalletUseCase = getUserWalletUseCase,
|
||||||
|
userWalletId = userWalletId,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -348,12 +360,16 @@ internal class TokenDetailsStateFactory(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStateWithUpdatedMenu(cardTypesResolver: CardTypesResolver, isBitcoin: Boolean): TokenDetailsState {
|
fun getStateWithUpdatedMenu(
|
||||||
|
cardTypesResolver: CardTypesResolver,
|
||||||
|
hasDerivations: Boolean,
|
||||||
|
isBitcoin: Boolean,
|
||||||
|
): TokenDetailsState {
|
||||||
return with(currentStateProvider()) {
|
return with(currentStateProvider()) {
|
||||||
copy(
|
copy(
|
||||||
topAppBarConfig = topAppBarConfig.copy(
|
topAppBarConfig = topAppBarConfig.copy(
|
||||||
tokenDetailsAppBarMenuConfig = topAppBarConfig.tokenDetailsAppBarMenuConfig
|
tokenDetailsAppBarMenuConfig = topAppBarConfig.tokenDetailsAppBarMenuConfig
|
||||||
?.updateMenu(cardTypesResolver, isBitcoin),
|
?.updateMenu(cardTypesResolver, hasDerivations, isBitcoin),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -367,13 +383,14 @@ internal class TokenDetailsStateFactory(
|
||||||
|
|
||||||
private fun TokenDetailsAppBarMenuConfig.updateMenu(
|
private fun TokenDetailsAppBarMenuConfig.updateMenu(
|
||||||
cardTypesResolver: CardTypesResolver,
|
cardTypesResolver: CardTypesResolver,
|
||||||
|
hasDerivations: Boolean,
|
||||||
isBitcoin: Boolean,
|
isBitcoin: Boolean,
|
||||||
): TokenDetailsAppBarMenuConfig? {
|
): TokenDetailsAppBarMenuConfig? {
|
||||||
if (cardTypesResolver.isSingleWalletWithToken()) return null
|
if (cardTypesResolver.isSingleWalletWithToken()) return null
|
||||||
val showGenerateExtendedKey = featureToggles.isGenerateXPubEnabled() && isBitcoin
|
val showGenerateExtendedKey = featureToggles.isGenerateXPubEnabled() && isBitcoin
|
||||||
return copy(
|
return copy(
|
||||||
items = buildList {
|
items = buildList {
|
||||||
if (showGenerateExtendedKey) {
|
if (showGenerateExtendedKey && hasDerivations) {
|
||||||
TokenDetailsAppBarMenuConfig.MenuItem(
|
TokenDetailsAppBarMenuConfig.MenuItem(
|
||||||
title = resourceReference(R.string.token_details_generate_xpub),
|
title = resourceReference(R.string.token_details_generate_xpub),
|
||||||
textColorProvider = { TangemTheme.colors.text.primary1 },
|
textColorProvider = { TangemTheme.colors.text.primary1 },
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||||
import com.tangem.domain.card.GetExtendedPublicKeyForCurrencyUseCase
|
import com.tangem.domain.card.GetExtendedPublicKeyForCurrencyUseCase
|
||||||
|
import com.tangem.domain.card.NetworkHasDerivationUseCase
|
||||||
import com.tangem.domain.common.util.cardTypesResolver
|
import com.tangem.domain.common.util.cardTypesResolver
|
||||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||||
import com.tangem.domain.redux.ReduxStateHolder
|
import com.tangem.domain.redux.ReduxStateHolder
|
||||||
|
|
@ -108,6 +109,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
||||||
private val stakingFeatureToggles: StakingFeatureToggles,
|
private val stakingFeatureToggles: StakingFeatureToggles,
|
||||||
private val getStakingAvailabilityUseCase: GetStakingAvailabilityUseCase,
|
private val getStakingAvailabilityUseCase: GetStakingAvailabilityUseCase,
|
||||||
private val getYieldUseCase: GetYieldUseCase,
|
private val getYieldUseCase: GetYieldUseCase,
|
||||||
|
private val networkHasDerivationUseCase: NetworkHasDerivationUseCase,
|
||||||
private val swapRepository: SwapRepository,
|
private val swapRepository: SwapRepository,
|
||||||
private val swapTransactionRepository: SwapTransactionRepository,
|
private val swapTransactionRepository: SwapTransactionRepository,
|
||||||
private val quotesRepository: QuotesRepository,
|
private val quotesRepository: QuotesRepository,
|
||||||
|
|
@ -118,8 +120,8 @@ internal class TokenDetailsViewModel @Inject constructor(
|
||||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||||
private val hapticManager: HapticManager,
|
private val hapticManager: HapticManager,
|
||||||
private val clipboardManager: ClipboardManager,
|
private val clipboardManager: ClipboardManager,
|
||||||
|
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||||
tokenDetailsFeatureToggles: TokenDetailsFeatureToggles,
|
tokenDetailsFeatureToggles: TokenDetailsFeatureToggles,
|
||||||
getUserWalletUseCase: GetUserWalletUseCase,
|
|
||||||
deepLinksRegistry: DeepLinksRegistry,
|
deepLinksRegistry: DeepLinksRegistry,
|
||||||
savedStateHandle: SavedStateHandle,
|
savedStateHandle: SavedStateHandle,
|
||||||
) : ViewModel(), DefaultLifecycleObserver, TokenDetailsClickIntents {
|
) : ViewModel(), DefaultLifecycleObserver, TokenDetailsClickIntents {
|
||||||
|
|
@ -156,6 +158,9 @@ internal class TokenDetailsViewModel @Inject constructor(
|
||||||
decimals = cryptoCurrency.decimals,
|
decimals = cryptoCurrency.decimals,
|
||||||
featureToggles = tokenDetailsFeatureToggles,
|
featureToggles = tokenDetailsFeatureToggles,
|
||||||
stakingFeatureToggles = stakingFeatureToggles,
|
stakingFeatureToggles = stakingFeatureToggles,
|
||||||
|
userWalletId = userWalletId,
|
||||||
|
networkHasDerivationUseCase = networkHasDerivationUseCase,
|
||||||
|
getUserWalletUseCase = getUserWalletUseCase,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val exchangeStatusFactory by lazy(mode = LazyThreadSafetyMode.NONE) {
|
private val exchangeStatusFactory by lazy(mode = LazyThreadSafetyMode.NONE) {
|
||||||
|
|
@ -395,8 +400,11 @@ internal class TokenDetailsViewModel @Inject constructor(
|
||||||
|
|
||||||
private fun updateTopBarMenu() {
|
private fun updateTopBarMenu() {
|
||||||
viewModelScope.launch(dispatchers.main) {
|
viewModelScope.launch(dispatchers.main) {
|
||||||
|
val hasDerivations =
|
||||||
|
networkHasDerivationUseCase(userWallet.scanResponse, cryptoCurrency.network).getOrElse { false }
|
||||||
internalUiState.value = stateFactory.getStateWithUpdatedMenu(
|
internalUiState.value = stateFactory.getStateWithUpdatedMenu(
|
||||||
cardTypesResolver = userWallet.scanResponse.cardTypesResolver,
|
cardTypesResolver = userWallet.scanResponse.cardTypesResolver,
|
||||||
|
hasDerivations = hasDerivations,
|
||||||
isBitcoin = isBitcoin(cryptoCurrency.network.id.value),
|
isBitcoin = isBitcoin(cryptoCurrency.network.id.value),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue