Updated on 2026-08-14

This commit is contained in:
Tangem 2024-07-15 18:47:45 +05:00
commit ec7dcde2d3
5 changed files with 79 additions and 11 deletions

View file

@ -84,4 +84,10 @@ internal object CardDomainModule {
fun provideResetCardUseCase(tangemSdkManager: TangemSdkManager): ResetCardUseCase {
return DefaultResetCardUseCase(tangemSdkManager)
}
@Provides
@Singleton
fun provideNetworkHasDerivationUseCase(): NetworkHasDerivationUseCase {
return NetworkHasDerivationUseCase()
}
}

View file

@ -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) }
}
}

View file

@ -1,5 +1,6 @@
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.transactions.state.TxHistoryState
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.resourceReference
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.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.components.TokenDetailsActionButton
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsPullToRefreshConfig
@ -25,6 +29,9 @@ import kotlinx.coroutines.flow.MutableStateFlow
internal class TokenDetailsSkeletonStateConverter(
private val clickIntents: TokenDetailsClickIntents,
private val featureToggles: TokenDetailsFeatureToggles,
private val networkHasDerivationUseCase: NetworkHasDerivationUseCase,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val userWalletId: UserWalletId,
) : Converter<CryptoCurrency, TokenDetailsState> {
private val iconStateConverter by lazy { TokenDetailsIconStateConverter() }
@ -78,13 +85,7 @@ internal class TokenDetailsSkeletonStateConverter(
private fun createMenu(cryptoCurrency: CryptoCurrency): TokenDetailsAppBarMenuConfig = TokenDetailsAppBarMenuConfig(
items = buildList {
if (featureToggles.isGenerateXPubEnabled() && isBitcoin(cryptoCurrency.network.id.value)) {
TokenDetailsAppBarMenuConfig.MenuItem(
title = resourceReference(R.string.token_details_generate_xpub),
textColorProvider = { TangemTheme.colors.text.primary1 },
onClick = clickIntents::onGenerateExtendedKey,
).let(::add)
}
addGenerateXPubMenuItem(cryptoCurrency)
TokenDetailsAppBarMenuConfig.MenuItem(
title = TextReference.Res(id = R.string.token_details_hide_token),
textColorProvider = { TangemTheme.colors.text.warning },
@ -93,6 +94,26 @@ internal class TokenDetailsSkeletonStateConverter(
}.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> {
return persistentListOf(
TokenDetailsActionButton.Buy(dimContent = false, onClick = {}),

View file

@ -15,6 +15,7 @@ import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.res.TangemTheme
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.card.NetworkHasDerivationUseCase
import com.tangem.domain.common.CardTypesResolver
import com.tangem.domain.staking.model.StakingAvailability
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.TxHistoryListError
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.components.TokenDetailsDialogConfig
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 clickIntents: TokenDetailsClickIntents,
private val featureToggles: TokenDetailsFeatureToggles,
private val networkHasDerivationUseCase: NetworkHasDerivationUseCase,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val userWalletId: UserWalletId,
stakingFeatureToggles: StakingFeatureToggles,
symbol: String,
decimals: Int,
@ -55,6 +64,9 @@ internal class TokenDetailsStateFactory(
TokenDetailsSkeletonStateConverter(
clickIntents = clickIntents,
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()) {
copy(
topAppBarConfig = topAppBarConfig.copy(
tokenDetailsAppBarMenuConfig = topAppBarConfig.tokenDetailsAppBarMenuConfig
?.updateMenu(cardTypesResolver, isBitcoin),
?.updateMenu(cardTypesResolver, hasDerivations, isBitcoin),
),
)
}
@ -367,13 +383,14 @@ internal class TokenDetailsStateFactory(
private fun TokenDetailsAppBarMenuConfig.updateMenu(
cardTypesResolver: CardTypesResolver,
hasDerivations: Boolean,
isBitcoin: Boolean,
): TokenDetailsAppBarMenuConfig? {
if (cardTypesResolver.isSingleWalletWithToken()) return null
val showGenerateExtendedKey = featureToggles.isGenerateXPubEnabled() && isBitcoin
return copy(
items = buildList {
if (showGenerateExtendedKey) {
if (showGenerateExtendedKey && hasDerivations) {
TokenDetailsAppBarMenuConfig.MenuItem(
title = resourceReference(R.string.token_details_generate_xpub),
textColorProvider = { TangemTheme.colors.text.primary1 },

View file

@ -25,6 +25,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.card.GetExtendedPublicKeyForCurrencyUseCase
import com.tangem.domain.card.NetworkHasDerivationUseCase
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.redux.ReduxStateHolder
@ -108,6 +109,7 @@ internal class TokenDetailsViewModel @Inject constructor(
private val stakingFeatureToggles: StakingFeatureToggles,
private val getStakingAvailabilityUseCase: GetStakingAvailabilityUseCase,
private val getYieldUseCase: GetYieldUseCase,
private val networkHasDerivationUseCase: NetworkHasDerivationUseCase,
private val swapRepository: SwapRepository,
private val swapTransactionRepository: SwapTransactionRepository,
private val quotesRepository: QuotesRepository,
@ -118,8 +120,8 @@ internal class TokenDetailsViewModel @Inject constructor(
private val analyticsEventsHandler: AnalyticsEventHandler,
private val hapticManager: HapticManager,
private val clipboardManager: ClipboardManager,
private val getUserWalletUseCase: GetUserWalletUseCase,
tokenDetailsFeatureToggles: TokenDetailsFeatureToggles,
getUserWalletUseCase: GetUserWalletUseCase,
deepLinksRegistry: DeepLinksRegistry,
savedStateHandle: SavedStateHandle,
) : ViewModel(), DefaultLifecycleObserver, TokenDetailsClickIntents {
@ -156,6 +158,9 @@ internal class TokenDetailsViewModel @Inject constructor(
decimals = cryptoCurrency.decimals,
featureToggles = tokenDetailsFeatureToggles,
stakingFeatureToggles = stakingFeatureToggles,
userWalletId = userWalletId,
networkHasDerivationUseCase = networkHasDerivationUseCase,
getUserWalletUseCase = getUserWalletUseCase,
)
private val exchangeStatusFactory by lazy(mode = LazyThreadSafetyMode.NONE) {
@ -395,8 +400,11 @@ internal class TokenDetailsViewModel @Inject constructor(
private fun updateTopBarMenu() {
viewModelScope.launch(dispatchers.main) {
val hasDerivations =
networkHasDerivationUseCase(userWallet.scanResponse, cryptoCurrency.network).getOrElse { false }
internalUiState.value = stateFactory.getStateWithUpdatedMenu(
cardTypesResolver = userWallet.scanResponse.cardTypesResolver,
hasDerivations = hasDerivations,
isBitcoin = isBitcoin(cryptoCurrency.network.id.value),
)
}