Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-13 23:15:22 +07:00
parent 18091cfea9
commit 8c9452f46c
17 changed files with 665 additions and 266 deletions

View file

@ -5,6 +5,7 @@ import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.demo.models.DemoConfig import com.tangem.domain.demo.models.DemoConfig
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.tokens.GetViewedTokenReceiveWarningUseCase
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.transaction.FeeRepository import com.tangem.domain.transaction.FeeRepository
import com.tangem.domain.transaction.TransactionRepository import com.tangem.domain.transaction.TransactionRepository
@ -231,6 +232,18 @@ internal object TransactionDomainModule {
) )
} }
@Provides
@Singleton
fun provideReceiveAddressesFactory(
getEnsNameUseCase: GetEnsNameUseCase,
getViewedTokenReceiveWarningUseCase: GetViewedTokenReceiveWarningUseCase,
): ReceiveAddressesFactory {
return ReceiveAddressesFactory(
getEnsNameUseCase = getEnsNameUseCase,
getViewedTokenReceiveWarningUseCase = getViewedTokenReceiveWarningUseCase,
)
}
@Provides @Provides
@Singleton @Singleton
fun provideGetReverseResolvedEnsAddressUseCase( fun provideGetReverseResolvedEnsAddressUseCase(

View file

@ -0,0 +1,124 @@
package com.tangem.domain.transaction.usecase
import com.tangem.domain.models.Asset
import com.tangem.domain.models.ReceiveAddressModel
import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.domain.models.TokenReceiveNotification
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.network.NetworkAddress
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.tokens.GetViewedTokenReceiveWarningUseCase
import com.tangem.domain.transaction.R
import com.tangem.lib.crypto.BlockchainUtils
class ReceiveAddressesFactory(
private val getEnsNameUseCase: GetEnsNameUseCase,
private val getViewedTokenReceiveWarningUseCase: GetViewedTokenReceiveWarningUseCase,
) {
suspend fun create(
status: CryptoCurrencyStatus,
userWalletId: UserWalletId,
notifications: List<TokenReceiveNotification> = emptyList(),
): TokenReceiveConfig? {
val addresses = status.value.networkAddress ?: return null
val cryptoCurrency = status.currency
val ensName = getEnsNameUseCase.invoke(
userWalletId = userWalletId,
network = cryptoCurrency.network,
address = addresses.defaultAddress.value,
)
val receiveAddresses = buildList {
ensName?.let { ens ->
add(
ReceiveAddressModel(
nameService = ReceiveAddressModel.NameService.Ens,
value = ens,
),
)
}
addresses.availableAddresses.map { address ->
add(
ReceiveAddressModel(
nameService = when (address.type) {
NetworkAddress.Address.Type.Primary -> ReceiveAddressModel.NameService.Default
NetworkAddress.Address.Type.Secondary -> ReceiveAddressModel.NameService.Legacy
},
value = address.value,
),
)
}
}
return TokenReceiveConfig(
shouldShowWarning = cryptoCurrency.name !in getViewedTokenReceiveWarningUseCase(),
cryptoCurrency = cryptoCurrency,
userWalletId = userWalletId,
showMemoDisclaimer = cryptoCurrency.network.transactionExtrasType != Network
.TransactionExtrasType.NONE,
receiveAddress = receiveAddresses,
tokenReceiveNotification = notifications,
)
}
suspend fun createForNft(
userWalletId: UserWalletId,
addresses: NetworkAddress,
network: Network,
nft: CryptoCurrency,
): TokenReceiveConfig {
val cryptoCurrency = nft
val ensName = getEnsNameUseCase.invoke(
userWalletId = userWalletId,
network = network,
address = addresses.defaultAddress.value,
)
val receiveAddresses = buildList {
ensName?.let { ens ->
add(
ReceiveAddressModel(
nameService = ReceiveAddressModel.NameService.Ens,
value = ens,
),
)
}
addresses.availableAddresses.map { address ->
add(
ReceiveAddressModel(
nameService = when (address.type) {
NetworkAddress.Address.Type.Primary -> ReceiveAddressModel.NameService.Default
NetworkAddress.Address.Type.Secondary -> ReceiveAddressModel.NameService.Legacy
},
value = address.value,
),
)
}
}
val notifications = buildList {
if (BlockchainUtils.isSolana(network.rawId)) {
add(
TokenReceiveNotification(
title = R.string.nft_receive_unsupported_types,
subtitle = R.string.nft_receive_unsupported_types_description,
),
)
}
}
return TokenReceiveConfig(
shouldShowWarning = Asset.NFT.name !in getViewedTokenReceiveWarningUseCase(),
cryptoCurrency = cryptoCurrency,
userWalletId = userWalletId,
showMemoDisclaimer = false,
receiveAddress = receiveAddresses,
tokenReceiveNotification = notifications,
asset = Asset.NFT,
)
}
}

View file

@ -1,25 +1,18 @@
package com.tangem.features.account.archived.di package com.tangem.features.account.archived.di
import com.tangem.core.decompose.di.ModelComponent
import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.Model
import com.tangem.features.account.ArchivedAccountListComponent
import com.tangem.features.account.archived.ArchivedAccountListModel import com.tangem.features.account.archived.ArchivedAccountListModel
import com.tangem.features.account.archived.DefaultArchivedAccountListComponent
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.ClassKey import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap
@Module @Module
@InstallIn(SingletonComponent::class) @InstallIn(ModelComponent::class)
internal interface AccountArchivedModule { internal interface AccountArchivedModule {
@Binds
fun bindArchivedAccountListComponentFactory(
impl: DefaultArchivedAccountListComponent.Factory,
): ArchivedAccountListComponent.Factory
@Binds @Binds
@IntoMap @IntoMap
@ClassKey(ArchivedAccountListModel::class) @ClassKey(ArchivedAccountListModel::class)

View file

@ -1,25 +1,18 @@
package com.tangem.features.account.createedit.di package com.tangem.features.account.createedit.di
import com.tangem.core.decompose.di.ModelComponent
import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.Model
import com.tangem.features.account.AccountCreateEditComponent
import com.tangem.features.account.createedit.AccountCreateEditModel import com.tangem.features.account.createedit.AccountCreateEditModel
import com.tangem.features.account.createedit.DefaultAccountCreateEditComponent
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.ClassKey import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap
@Module @Module
@InstallIn(SingletonComponent::class) @InstallIn(ModelComponent::class)
internal interface AccountCreateEditModule { internal interface AccountCreateEditModule {
@Binds
fun bindAccountCreateEditComponentFactory(
impl: DefaultAccountCreateEditComponent.Factory,
): AccountCreateEditComponent.Factory
@Binds @Binds
@IntoMap @IntoMap
@ClassKey(AccountCreateEditModel::class) @ClassKey(AccountCreateEditModel::class)

View file

@ -1,25 +1,18 @@
package com.tangem.features.account.details.di package com.tangem.features.account.details.di
import com.tangem.core.decompose.di.ModelComponent
import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.Model
import com.tangem.features.account.AccountDetailsComponent
import com.tangem.features.account.details.AccountDetailsModel import com.tangem.features.account.details.AccountDetailsModel
import com.tangem.features.account.details.DefaultAccountDetailsComponent
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.ClassKey import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap
@Module @Module
@InstallIn(SingletonComponent::class) @InstallIn(ModelComponent::class)
internal interface AccountDetailsModule { internal interface AccountDetailsModule {
@Binds
fun bindAccountDetailsComponentFactory(
impl: DefaultAccountDetailsComponent.Factory,
): AccountDetailsComponent.Factory
@Binds @Binds
@IntoMap @IntoMap
@ClassKey(AccountDetailsModel::class) @ClassKey(AccountDetailsModel::class)

View file

@ -1,8 +1,14 @@
package com.tangem.features.account.di package com.tangem.features.account.di
import com.tangem.features.account.AccountCreateEditComponent
import com.tangem.features.account.AccountDetailsComponent
import com.tangem.features.account.ArchivedAccountListComponent
import com.tangem.features.account.PortfolioFetcher import com.tangem.features.account.PortfolioFetcher
import com.tangem.features.account.PortfolioSelectorComponent import com.tangem.features.account.PortfolioSelectorComponent
import com.tangem.features.account.PortfolioSelectorController import com.tangem.features.account.PortfolioSelectorController
import com.tangem.features.account.archived.DefaultArchivedAccountListComponent
import com.tangem.features.account.createedit.DefaultAccountCreateEditComponent
import com.tangem.features.account.details.DefaultAccountDetailsComponent
import com.tangem.features.account.fetcher.DefaultPortfolioFetcher import com.tangem.features.account.fetcher.DefaultPortfolioFetcher
import com.tangem.features.account.selector.DefaultPortfolioSelectorComponent import com.tangem.features.account.selector.DefaultPortfolioSelectorComponent
import com.tangem.features.account.selector.DefaultPortfolioSelectorController import com.tangem.features.account.selector.DefaultPortfolioSelectorController
@ -25,4 +31,19 @@ internal interface AccountFeatureModule {
fun bindPortfolioSelectorComponentFactory( fun bindPortfolioSelectorComponentFactory(
impl: DefaultPortfolioSelectorComponent.Factory, impl: DefaultPortfolioSelectorComponent.Factory,
): PortfolioSelectorComponent.Factory ): PortfolioSelectorComponent.Factory
@Binds
fun bindAccountCreateEditComponentFactory(
impl: DefaultAccountCreateEditComponent.Factory,
): AccountCreateEditComponent.Factory
@Binds
fun bindAccountDetailsComponentFactory(
impl: DefaultAccountDetailsComponent.Factory,
): AccountDetailsComponent.Factory
@Binds
fun bindArchivedAccountListComponentFactory(
impl: DefaultArchivedAccountListComponent.Factory,
): ArchivedAccountListComponent.Factory
} }

View file

@ -0,0 +1,79 @@
package com.tangem.features.markets.portfolio.add.impl
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.extensions.compose.subscribeAsState
import com.arkivanov.decompose.router.slot.childSlot
import com.arkivanov.decompose.router.slot.dismiss
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.context.childByContext
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.features.markets.portfolio.add.impl.model.TokenActionsModel
import com.tangem.features.markets.portfolio.add.impl.ui.TokenActionsContent
import com.tangem.features.markets.portfolio.impl.analytics.PortfolioAnalyticsEvent
import com.tangem.features.markets.portfolio.impl.loader.PortfolioData
import com.tangem.features.tokenreceive.TokenReceiveComponent
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.Flow
internal class TokenActionsComponent @AssistedInject constructor(
@Assisted context: AppComponentContext,
@Assisted private val params: Params,
private val tokenReceiveComponentFactory: TokenReceiveComponent.Factory,
) : AppComponentContext by context, ComposableContentComponent {
private val model: TokenActionsModel = getOrCreateModel(params)
private val bottomSheetSlot = childSlot(
source = model.bottomSheetNavigation,
serializer = TokenReceiveConfig.serializer(),
handleBackButton = false,
childFactory = ::bottomSheetChild,
)
@Composable
override fun Content(modifier: Modifier) {
val state = model.uiState.collectAsStateWithLifecycle()
val bottomSheet by bottomSheetSlot.subscribeAsState()
val tokenActionsUM = state.value ?: return
TokenActionsContent(
modifier = modifier,
state = tokenActionsUM,
)
bottomSheet.child?.instance?.BottomSheet()
}
private fun bottomSheetChild(
config: TokenReceiveConfig,
componentContext: ComponentContext,
): ComposableBottomSheetComponent = tokenReceiveComponentFactory.create(
context = childByContext(componentContext),
params = TokenReceiveComponent.Params(
config = config,
onDismiss = model.bottomSheetNavigation::dismiss,
),
)
data class Params(
val eventBuilder: PortfolioAnalyticsEvent.EventBuilder,
val data: Flow<PortfolioData.CryptoCurrencyData>,
val callbacks: Callbacks,
)
interface Callbacks {
fun onLaterClick()
}
@AssistedFactory
interface Factory : ComponentFactory<Params, TokenActionsComponent> {
override fun create(context: AppComponentContext, params: Params): TokenActionsComponent
}
}

View file

@ -0,0 +1,80 @@
package com.tangem.features.markets.portfolio.add.impl.model
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.domain.transaction.usecase.ReceiveAddressesFactory
import com.tangem.features.markets.portfolio.add.impl.TokenActionsComponent
import com.tangem.features.markets.portfolio.add.impl.ui.state.TokenActionsUM
import com.tangem.features.markets.portfolio.impl.model.TokenActionsHandler
import com.tangem.features.markets.portfolio.impl.model.TokenActionsHandler.HandledQuickAction
import com.tangem.features.markets.portfolio.impl.ui.state.TokenActionsBSContentUM
import com.tangem.utils.Provider
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject
@ModelScoped
@Suppress("LongParameterList")
internal class TokenActionsModel @Inject constructor(
paramsContainer: ParamsContainer,
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
tokenActionsIntentsFactory: TokenActionsHandler.Factory,
override val dispatchers: CoroutineDispatcherProvider,
private val uiBuilder: TokenActionsUiBuilder,
private val analyticsEventHandler: AnalyticsEventHandler,
private val receiveAddressesFactory: ReceiveAddressesFactory,
) : Model() {
private val params = paramsContainer.require<TokenActionsComponent.Params>()
private val analyticsEventBuilder get() = params.eventBuilder
private val currentAppCurrency = getSelectedAppCurrencyUseCase.invokeOrDefault()
.stateIn(
scope = modelScope,
started = SharingStarted.Eagerly,
initialValue = AppCurrency.Default,
)
private val tokenActionsHandler: TokenActionsHandler =
tokenActionsIntentsFactory.create(
currentAppCurrency = Provider { currentAppCurrency.value },
updateTokenReceiveBSConfig = { },
onHandleQuickAction = { handledAction -> handledQuickAction(handledAction) },
)
val bottomSheetNavigation: SlotNavigation<TokenReceiveConfig> = SlotNavigation()
val uiState: StateFlow<TokenActionsUM?> = params.data
.mapLatest { uiBuilder.build(it, tokenActionsHandler) }
.stateIn(
scope = modelScope,
started = SharingStarted.Eagerly,
initialValue = null,
)
private fun handledQuickAction(handledAction: HandledQuickAction) {
val event = analyticsEventBuilder.quickActionClick(
actionUM = handledAction.action,
blockchainName = handledAction.cryptoCurrencyData.status.currency.network.name,
)
analyticsEventHandler.send(event)
val isReceive = handledAction.action == TokenActionsBSContentUM.Action.Receive
if (!isReceive) return
modelScope.launch {
val tokenConfig = receiveAddressesFactory.create(
status = handledAction.cryptoCurrencyData.status,
userWalletId = handledAction.cryptoCurrencyData.userWallet.walletId,
) ?: return@launch
bottomSheetNavigation.activate(tokenConfig)
}
}
}

View file

@ -0,0 +1,39 @@
package com.tangem.features.markets.portfolio.add.impl.model
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.stringReference
import com.tangem.features.markets.portfolio.add.impl.TokenActionsComponent
import com.tangem.features.markets.portfolio.add.impl.ui.state.TokenActionsUM
import com.tangem.features.markets.portfolio.impl.loader.PortfolioData
import com.tangem.features.markets.portfolio.impl.model.PortfolioTokenUMConverter
import com.tangem.features.markets.portfolio.impl.model.TokenActionsHandler
import javax.inject.Inject
@ModelScoped
internal class TokenActionsUiBuilder @Inject constructor(
paramsContainer: ParamsContainer,
) {
private val params = paramsContainer.require<TokenActionsComponent.Params>()
fun build(data: PortfolioData.CryptoCurrencyData, tokenActionsHandler: TokenActionsHandler): TokenActionsUM {
val status = data.status
val tokenUM = TokenItemState.Content(
id = status.currency.id.value,
iconState = CryptoCurrencyToIconStateConverter().convert(status.currency),
titleState = TokenItemState.TitleState.Content(stringReference(status.currency.name)),
fiatAmountState = null,
subtitle2State = null,
subtitleState = TokenItemState.SubtitleState.TextContent(stringReference(status.currency.symbol)),
onItemClick = null,
onItemLongClick = null,
)
return TokenActionsUM(
token = tokenUM,
onLaterClick = { params.callbacks.onLaterClick() },
quickActions = PortfolioTokenUMConverter.quickActions(data, tokenActionsHandler),
)
}
}

View file

@ -0,0 +1,204 @@
package com.tangem.features.markets.portfolio.add.impl.ui
import android.content.res.Configuration
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
import com.tangem.core.ui.components.SecondaryButton
import com.tangem.core.ui.components.SpacerH
import com.tangem.core.ui.components.SpacerH16
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.icons.badge.drawBadge
import com.tangem.core.ui.components.token.TokenItem
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.haptic.TangemHapticEffect
import com.tangem.core.ui.res.LocalHapticManager
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.markets.impl.R
import com.tangem.features.markets.portfolio.add.impl.ui.state.TokenActionsUM
import com.tangem.features.markets.portfolio.impl.ui.state.PortfolioTokenUM
import com.tangem.features.markets.portfolio.impl.ui.state.QuickActionUM
import kotlinx.collections.immutable.persistentListOf
import java.util.UUID
@Composable
internal fun TokenActionsContent(state: TokenActionsUM, modifier: Modifier = Modifier) {
Column(
modifier = modifier.fillMaxWidth(),
) {
TokenItem(
modifier = Modifier
.clip(RoundedCornerShape(TangemTheme.dimens.radius14))
.background(color = TangemTheme.colors.background.action),
state = state.token,
isBalanceHidden = false,
)
SpacerH(TangemTheme.dimens.spacing14)
Column(
modifier = Modifier
.clip(RoundedCornerShape(TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.action),
) {
state.quickActions.actions.fastForEach {
key(it.title) {
ActionRow(
state = it,
onClick = { state.quickActions.onQuickActionClick(it) },
onLongClick = { state.quickActions.onQuickActionLongClick(it) },
)
}
}
}
SpacerH16()
SecondaryButton(
modifier = modifier.fillMaxWidth(),
text = stringResourceSafe(R.string.common_later),
onClick = state.onLaterClick,
)
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun ActionRow(
state: QuickActionUM,
onClick: () -> Unit,
onLongClick: (() -> Unit),
modifier: Modifier = Modifier,
) {
val hapticManager = LocalHapticManager.current
val onLongClickInternal = {
hapticManager.perform(TangemHapticEffect.View.LongPress)
onLongClick()
}
Row(
modifier = modifier
.fillMaxWidth()
.combinedClickable(
onLongClick = onLongClickInternal.takeIf { state.longClickAvailable },
onClick = {
hapticManager.perform(TangemHapticEffect.View.SegmentTick)
onClick()
},
)
.padding(horizontal = TangemTheme.dimens.spacing12, vertical = TangemTheme.dimens.spacing15),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
) {
val containerColor = TangemTheme.colors.background.action
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.background(
color = TangemTheme.colors.icon.accent.copy(alpha = 0.1f),
shape = CircleShape,
)
.size(36.dp)
.drawWithContent {
drawContent()
if (state is QuickActionUM.Exchange && state.showBadge) {
drawBadge(containerColor = containerColor, offset = 4.dp)
}
},
) {
Icon(
modifier = Modifier.requiredSize(TangemTheme.dimens.size16),
imageVector = ImageVector.vectorResource(id = state.icon),
contentDescription = null,
tint = TangemTheme.colors.icon.accent,
)
}
Column(
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing2),
) {
Text(
text = state.title.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.primary1,
)
Text(
text = state.description.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
)
}
}
}
@Preview(widthDp = 360, showBackground = true)
@Preview(widthDp = 360, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview(@PreviewParameter(TokenActionsContentPreviewProvider::class) state: TokenActionsUM) {
TangemThemePreview {
TokenActionsContent(
state = state,
)
}
}
private class TokenActionsContentPreviewProvider : PreviewParameterProvider<TokenActionsUM> {
private val tokenState
get() = TokenItemState.Content(
id = UUID.randomUUID().toString(),
iconState = CurrencyIconState.TokenIcon(
url = null,
topBadgeIconResId = R.drawable.img_eth_22,
fallbackTint = TangemColorPalette.Black,
fallbackBackground = TangemColorPalette.Meadow,
isGrayscale = false,
shouldShowCustomBadge = false,
),
titleState = TokenItemState.TitleState.Content(
text = stringReference(value = "Tether"),
),
fiatAmountState = null,
subtitle2State = null,
subtitleState = TokenItemState.SubtitleState.TextContent(value = stringReference("USDT")),
onItemClick = {},
onItemLongClick = {},
)
override val values: Sequence<TokenActionsUM>
get() = sequenceOf(
TokenActionsUM(
quickActions = PortfolioTokenUM.QuickActions(
actions = persistentListOf(
QuickActionUM.Buy,
QuickActionUM.Exchange(showBadge = true),
QuickActionUM.Receive,
),
onQuickActionClick = {},
onQuickActionLongClick = {},
),
token = tokenState,
onLaterClick = {},
),
)
}

View file

@ -0,0 +1,10 @@
package com.tangem.features.markets.portfolio.add.impl.ui.state
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.features.markets.portfolio.impl.ui.state.PortfolioTokenUM
internal data class TokenActionsUM(
val token: TokenItemState,
val quickActions: PortfolioTokenUM.QuickActions,
val onLaterClick: () -> Unit,
)

View file

@ -2,9 +2,9 @@ package com.tangem.features.markets.portfolio.impl.model
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import arrow.core.getOrElse import arrow.core.getOrElse
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
import com.arkivanov.decompose.router.slot.SlotNavigation import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate import com.arkivanov.decompose.router.slot.activate
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.Model
@ -22,16 +22,13 @@ import com.tangem.domain.managetokens.CheckCurrencyUnsupportedUseCase
import com.tangem.domain.managetokens.model.CurrencyUnsupportedState import com.tangem.domain.managetokens.model.CurrencyUnsupportedState
import com.tangem.domain.markets.SaveMarketTokensUseCase import com.tangem.domain.markets.SaveMarketTokensUseCase
import com.tangem.domain.markets.TokenMarketInfo import com.tangem.domain.markets.TokenMarketInfo
import com.tangem.domain.models.ReceiveAddressModel
import com.tangem.domain.models.TokenReceiveConfig import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network import com.tangem.domain.models.network.Network
import com.tangem.domain.models.network.NetworkAddress
import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.isMultiCurrency import com.tangem.domain.models.wallet.isMultiCurrency
import com.tangem.domain.tokens.GetViewedTokenReceiveWarningUseCase import com.tangem.domain.transaction.usecase.ReceiveAddressesFactory
import com.tangem.domain.transaction.usecase.GetEnsNameUseCase
import com.tangem.domain.wallets.usecase.ColdWalletAndHasMissedDerivationsUseCase import com.tangem.domain.wallets.usecase.ColdWalletAndHasMissedDerivationsUseCase
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
import com.tangem.features.markets.impl.R import com.tangem.features.markets.impl.R
@ -70,9 +67,8 @@ internal class MarketsPortfolioModel @Inject constructor(
private val addToPortfolioManager: AddToPortfolioManager, private val addToPortfolioManager: AddToPortfolioManager,
private val analyticsEventHandler: AnalyticsEventHandler, private val analyticsEventHandler: AnalyticsEventHandler,
private val tokenReceiveFeatureToggle: TokenReceiveFeatureToggle, private val tokenReceiveFeatureToggle: TokenReceiveFeatureToggle,
private val getViewedTokenReceiveWarningUseCase: GetViewedTokenReceiveWarningUseCase,
private val getEnsNameUseCase: GetEnsNameUseCase,
private val userWalletImageFetcher: UserWalletImageFetcher, private val userWalletImageFetcher: UserWalletImageFetcher,
private val receiveAddressesFactory: ReceiveAddressesFactory,
) : Model() { ) : Model() {
val state: StateFlow<MyPortfolioUM> get() = _state val state: StateFlow<MyPortfolioUM> get() = _state
@ -374,50 +370,16 @@ internal class MarketsPortfolioModel @Inject constructor(
} }
private fun configureReceiveAddresses(quickAction: TokenActionsHandler.HandledQuickAction) { private fun configureReceiveAddresses(quickAction: TokenActionsHandler.HandledQuickAction) {
when (quickAction.action) { val isNewReceive = quickAction.action == TokenActionsBSContentUM.Action.Receive &&
TokenActionsBSContentUM.Action.Receive -> { tokenReceiveFeatureToggle.isNewTokenReceiveEnabled
val addresses = quickAction.cryptoCurrencyData.status.value.networkAddress ?: return if (isNewReceive) {
val cryptoCurrency = quickAction.cryptoCurrencyData.status.currency
modelScope.launch { modelScope.launch {
val ensName = getEnsNameUseCase.invoke( val tokenConfig = receiveAddressesFactory.create(
status = quickAction.cryptoCurrencyData.status,
userWalletId = quickAction.cryptoCurrencyData.userWallet.walletId, userWalletId = quickAction.cryptoCurrencyData.userWallet.walletId,
network = cryptoCurrency.network, ) ?: return@launch
address = addresses.defaultAddress.value,
)
val receiveAddresses = buildList {
ensName?.let { ens ->
add(
ReceiveAddressModel(
nameService = ReceiveAddressModel.NameService.Ens,
value = ens,
),
)
}
addresses.availableAddresses.map { address ->
add(
ReceiveAddressModel(
nameService = when (address.type) {
NetworkAddress.Address.Type.Primary -> ReceiveAddressModel.NameService.Default
NetworkAddress.Address.Type.Secondary -> ReceiveAddressModel.NameService.Legacy
},
value = address.value,
),
)
}
}
val tokenConfig = TokenReceiveConfig(
shouldShowWarning = cryptoCurrency.name !in getViewedTokenReceiveWarningUseCase(),
cryptoCurrency = cryptoCurrency,
userWalletId = quickAction.cryptoCurrencyData.userWallet.walletId,
showMemoDisclaimer = cryptoCurrency.network.transactionExtrasType != Network
.TransactionExtrasType.NONE,
receiveAddress = receiveAddresses,
)
bottomSheetNavigation.activate(tokenConfig) bottomSheetNavigation.activate(tokenConfig)
} }
} }
else -> Unit
}
} }
} }

View file

@ -42,11 +42,15 @@ internal class PortfolioTokenUMConverter(
walletId = value.userWallet.walletId, walletId = value.userWallet.walletId,
isBalanceHidden = isBalanceHidden, isBalanceHidden = isBalanceHidden,
isQuickActionsShown = false, isQuickActionsShown = false,
quickActions = quickActions(cryptoData = value), quickActions = quickActions(cryptoData = value, tokenActionsHandler = tokenActionsHandler),
) )
} }
private fun quickActions(cryptoData: PortfolioData.CryptoCurrencyData): PortfolioTokenUM.QuickActions { companion object {
fun quickActions(
cryptoData: PortfolioData.CryptoCurrencyData,
tokenActionsHandler: TokenActionsHandler,
): PortfolioTokenUM.QuickActions {
return PortfolioTokenUM.QuickActions( return PortfolioTokenUM.QuickActions(
actions = toQuickActions(cryptoData.actions), actions = toQuickActions(cryptoData.actions),
onQuickActionClick = { onQuickActionClick = {
@ -94,3 +98,4 @@ internal class PortfolioTokenUMConverter(
} }
}.toImmutableList() }.toImmutableList()
} }
}

View file

@ -14,10 +14,7 @@ import com.tangem.core.ui.components.fields.entity.SearchBarUM
import com.tangem.core.ui.extensions.resourceReference 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.message.DialogMessage import com.tangem.core.ui.message.DialogMessage
import com.tangem.domain.models.Asset
import com.tangem.domain.models.ReceiveAddressModel
import com.tangem.domain.models.TokenReceiveConfig import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.domain.models.TokenReceiveNotification
import com.tangem.domain.models.network.Network import com.tangem.domain.models.network.Network
import com.tangem.domain.models.network.NetworkAddress import com.tangem.domain.models.network.NetworkAddress
import com.tangem.domain.models.network.NetworkStatus import com.tangem.domain.models.network.NetworkStatus
@ -26,8 +23,7 @@ import com.tangem.domain.nft.GetNFTCurrencyUseCase
import com.tangem.domain.nft.GetNFTNetworkStatusUseCase import com.tangem.domain.nft.GetNFTNetworkStatusUseCase
import com.tangem.domain.nft.GetNFTNetworksUseCase import com.tangem.domain.nft.GetNFTNetworksUseCase
import com.tangem.domain.nft.analytics.NFTAnalyticsEvent import com.tangem.domain.nft.analytics.NFTAnalyticsEvent
import com.tangem.domain.tokens.GetViewedTokenReceiveWarningUseCase import com.tangem.domain.transaction.usecase.ReceiveAddressesFactory
import com.tangem.domain.transaction.usecase.GetEnsNameUseCase
import com.tangem.features.nft.impl.R import com.tangem.features.nft.impl.R
import com.tangem.features.nft.receive.NFTReceiveComponent import com.tangem.features.nft.receive.NFTReceiveComponent
import com.tangem.features.nft.receive.entity.NFTReceiveUM import com.tangem.features.nft.receive.entity.NFTReceiveUM
@ -36,7 +32,6 @@ import com.tangem.features.nft.receive.entity.transformer.ToggleSearchBarTransfo
import com.tangem.features.nft.receive.entity.transformer.UpdateDataStateTransformer import com.tangem.features.nft.receive.entity.transformer.UpdateDataStateTransformer
import com.tangem.features.nft.receive.entity.transformer.UpdateSearchQueryTransformer import com.tangem.features.nft.receive.entity.transformer.UpdateSearchQueryTransformer
import com.tangem.features.tokenreceive.TokenReceiveFeatureToggle import com.tangem.features.tokenreceive.TokenReceiveFeatureToggle
import com.tangem.lib.crypto.BlockchainUtils
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
@ -56,9 +51,8 @@ internal class NFTReceiveModel @Inject constructor(
private val analyticsEventHandler: AnalyticsEventHandler, private val analyticsEventHandler: AnalyticsEventHandler,
private val messageSender: UiMessageSender, private val messageSender: UiMessageSender,
private val tokenReceiveFeatureToggle: TokenReceiveFeatureToggle, private val tokenReceiveFeatureToggle: TokenReceiveFeatureToggle,
private val getViewedTokenReceiveWarningUseCase: GetViewedTokenReceiveWarningUseCase,
private val getEnsNameUseCase: GetEnsNameUseCase,
private val getNFTCurrencyUseCase: GetNFTCurrencyUseCase, private val getNFTCurrencyUseCase: GetNFTCurrencyUseCase,
private val receiveAddressesFactory: ReceiveAddressesFactory,
paramsContainer: ParamsContainer, paramsContainer: ParamsContainer,
) : Model() { ) : Model() {
@ -196,54 +190,11 @@ internal class NFTReceiveModel @Inject constructor(
private suspend fun configureReceiveAddresses(addresses: NetworkAddress, network: Network): TokenReceiveConfig { private suspend fun configureReceiveAddresses(addresses: NetworkAddress, network: Network): TokenReceiveConfig {
val cryptoCurrency = getNFTCurrencyUseCase.invoke(network) val cryptoCurrency = getNFTCurrencyUseCase.invoke(network)
return receiveAddressesFactory.createForNft(
val ensName = getEnsNameUseCase.invoke(
userWalletId = params.userWalletId, userWalletId = params.userWalletId,
addresses = addresses,
network = network, network = network,
address = addresses.defaultAddress.value, nft = cryptoCurrency,
)
val receiveAddresses = buildList {
ensName?.let { ens ->
add(
ReceiveAddressModel(
nameService = ReceiveAddressModel.NameService.Ens,
value = ens,
),
)
}
addresses.availableAddresses.map { address ->
add(
ReceiveAddressModel(
nameService = when (address.type) {
NetworkAddress.Address.Type.Primary -> ReceiveAddressModel.NameService.Default
NetworkAddress.Address.Type.Secondary -> ReceiveAddressModel.NameService.Legacy
},
value = address.value,
),
)
}
}
val notifications = buildList {
if (BlockchainUtils.isSolana(network.rawId)) {
add(
TokenReceiveNotification(
title = R.string.nft_receive_unsupported_types,
subtitle = R.string.nft_receive_unsupported_types_description,
),
)
}
}
return TokenReceiveConfig(
shouldShowWarning = Asset.NFT.name !in getViewedTokenReceiveWarningUseCase(),
cryptoCurrency = cryptoCurrency,
userWalletId = params.userWalletId,
showMemoDisclaimer = false,
receiveAddress = receiveAddresses,
tokenReceiveNotification = notifications,
asset = Asset.NFT,
) )
} }
} }

View file

@ -47,8 +47,8 @@ internal class AccountAwardConverter(
id = currency.id.value, id = currency.id.value,
iconState = CryptoCurrencyToIconStateConverter().convert(currency), iconState = CryptoCurrencyToIconStateConverter().convert(currency),
titleState = TokenItemState.TitleState.Content(stringReference(currency.name)), titleState = TokenItemState.TitleState.Content(stringReference(currency.name)),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = ""), fiatAmountState = null,
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = ""), subtitle2State = null,
subtitleState = TokenItemState.SubtitleState.TextContent(stringReference(currency.symbol)), subtitleState = TokenItemState.SubtitleState.TextContent(stringReference(currency.symbol)),
onItemClick = null, onItemClick = null,
onItemLongClick = null, onItemLongClick = null,

View file

@ -36,12 +36,9 @@ import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.card.common.util.cardTypesResolver import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.models.ReceiveAddressModel
import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.domain.models.TokenReceiveNotification import com.tangem.domain.models.TokenReceiveNotification
import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.network.NetworkAddress import com.tangem.domain.models.network.NetworkAddress
import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
@ -139,8 +136,7 @@ internal class TokenDetailsModel @Inject constructor(
private val tokenDetailsDeepLinkActionListener: TokenDetailsDeepLinkActionListener, private val tokenDetailsDeepLinkActionListener: TokenDetailsDeepLinkActionListener,
private val analyticsExceptionHandler: AnalyticsExceptionHandler, private val analyticsExceptionHandler: AnalyticsExceptionHandler,
private val tokenReceiveFeatureToggle: TokenReceiveFeatureToggle, private val tokenReceiveFeatureToggle: TokenReceiveFeatureToggle,
private val getViewedTokenReceiveWarningUseCase: GetViewedTokenReceiveWarningUseCase, private val receiveAddressesFactory: ReceiveAddressesFactory,
private val getEnsNameUseCase: GetEnsNameUseCase,
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles, private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
private val saveViewedYieldSupplyWarningUseCase: SaveViewedYieldSupplyWarningUseCase, private val saveViewedYieldSupplyWarningUseCase: SaveViewedYieldSupplyWarningUseCase,
private val saveViewedTokenReceiveWarningUseCase: SaveViewedTokenReceiveWarningUseCase, private val saveViewedTokenReceiveWarningUseCase: SaveViewedTokenReceiveWarningUseCase,
@ -1058,34 +1054,10 @@ internal class TokenDetailsModel @Inject constructor(
.launchIn(modelScope) .launchIn(modelScope)
} }
private suspend fun configureReceiveAddresses(addresses: NetworkAddress): TokenDetailsBottomSheetConfig { private suspend fun configureReceiveAddresses(
val ensName = getEnsNameUseCase.invoke( cryptoCurrencyStatus: CryptoCurrencyStatus?,
userWalletId = userWalletId, ): TokenDetailsBottomSheetConfig? {
network = cryptoCurrency.network, cryptoCurrencyStatus ?: return null
address = addresses.defaultAddress.value,
)
val receiveAddresses = buildList {
ensName?.let { ens ->
add(
ReceiveAddressModel(
nameService = ReceiveAddressModel.NameService.Ens,
value = ens,
),
)
}
addresses.availableAddresses.map { address ->
add(
ReceiveAddressModel(
nameService = when (address.type) {
NetworkAddress.Address.Type.Primary -> ReceiveAddressModel.NameService.Default
NetworkAddress.Address.Type.Secondary -> ReceiveAddressModel.NameService.Legacy
},
value = address.value,
),
)
}
}
val notifications = buildList { val notifications = buildList {
if (isActiveYieldSupply()) { if (isActiveYieldSupply()) {
@ -1099,16 +1071,13 @@ internal class TokenDetailsModel @Inject constructor(
} }
} }
return TokenDetailsBottomSheetConfig.Receive( val receiveConfig = receiveAddressesFactory.create(
TokenReceiveConfig( status = cryptoCurrencyStatus,
shouldShowWarning = cryptoCurrency.name !in getViewedTokenReceiveWarningUseCase(),
cryptoCurrency = cryptoCurrency,
userWalletId = userWalletId, userWalletId = userWalletId,
showMemoDisclaimer = cryptoCurrency.network.transactionExtrasType != Network.TransactionExtrasType.NONE, notifications = notifications,
tokenReceiveNotification = notifications, ) ?: return null
receiveAddress = receiveAddresses,
), return TokenDetailsBottomSheetConfig.Receive(receiveConfig)
)
} }
private fun sendOneTimeBalanceLoadedAnalyticsEvent(cryptoCurrencyStatus: CryptoCurrencyStatus?) { private fun sendOneTimeBalanceLoadedAnalyticsEvent(cryptoCurrencyStatus: CryptoCurrencyStatus?) {
@ -1186,9 +1155,8 @@ internal class TokenDetailsModel @Inject constructor(
val networkAddress = cryptoCurrencyStatus?.value?.networkAddress ?: return val networkAddress = cryptoCurrencyStatus?.value?.networkAddress ?: return
if (tokenReceiveFeatureToggle.isNewTokenReceiveEnabled) { if (tokenReceiveFeatureToggle.isNewTokenReceiveEnabled) {
modelScope.launch { modelScope.launch {
bottomSheetNavigation.activate( configureReceiveAddresses(cryptoCurrencyStatus = cryptoCurrencyStatus)
configuration = configureReceiveAddresses(addresses = networkAddress), ?.let { bottomSheetNavigation.activate(it) }
)
} }
} else { } else {
analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ReceiveScreenOpened(cryptoCurrency.symbol)) analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ReceiveScreenOpened(cryptoCurrency.symbol))

View file

@ -29,7 +29,6 @@ import com.tangem.domain.core.utils.lceError
import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.exchange.RampStateManager import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.markets.TokenMarketParams import com.tangem.domain.markets.TokenMarketParams
import com.tangem.domain.models.ReceiveAddressModel
import com.tangem.domain.models.TokenReceiveConfig import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.currency.CryptoCurrencyStatus
@ -52,7 +51,7 @@ import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.AVAILABLE import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.AVAILABLE
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.toReasonAnalyticsText import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.toReasonAnalyticsText
import com.tangem.domain.tokens.model.details.TokenAction import com.tangem.domain.tokens.model.details.TokenAction
import com.tangem.domain.transaction.usecase.GetEnsNameUseCase import com.tangem.domain.transaction.usecase.ReceiveAddressesFactory
import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.usecase.GetExploreUrlUseCase import com.tangem.domain.wallets.usecase.GetExploreUrlUseCase
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
@ -145,9 +144,8 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
private val appRouter: AppRouter, private val appRouter: AppRouter,
private val rampStateManager: RampStateManager, private val rampStateManager: RampStateManager,
private val tokenReceiveFeatureToggle: TokenReceiveFeatureToggle, private val tokenReceiveFeatureToggle: TokenReceiveFeatureToggle,
private val getViewedTokenReceiveWarningUseCase: GetViewedTokenReceiveWarningUseCase,
private val saveViewedTokenReceiveWarningUseCase: SaveViewedTokenReceiveWarningUseCase, private val saveViewedTokenReceiveWarningUseCase: SaveViewedTokenReceiveWarningUseCase,
private val getEnsNameUseCase: GetEnsNameUseCase, private val receiveAddressesFactory: ReceiveAddressesFactory,
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles, private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
private val needShowYieldSupplyDepositedWarningUseCase: NeedShowYieldSupplyDepositedWarningUseCase, private val needShowYieldSupplyDepositedWarningUseCase: NeedShowYieldSupplyDepositedWarningUseCase,
private val saveViewedYieldSupplyWarningUseCase: SaveViewedYieldSupplyWarningUseCase, private val saveViewedYieldSupplyWarningUseCase: SaveViewedYieldSupplyWarningUseCase,
@ -708,44 +706,10 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
} }
private suspend fun configureReceiveAddresses(cryptoCurrencyStatus: CryptoCurrencyStatus): TokenReceiveConfig? { private suspend fun configureReceiveAddresses(cryptoCurrencyStatus: CryptoCurrencyStatus): TokenReceiveConfig? {
val networkAddress = cryptoCurrencyStatus.value.networkAddress ?: return null
val userWalletId = stateHolder.getSelectedWalletId() val userWalletId = stateHolder.getSelectedWalletId()
return receiveAddressesFactory.create(
val ensName = getEnsNameUseCase.invoke( status = cryptoCurrencyStatus,
userWalletId = userWalletId, userWalletId = userWalletId,
network = cryptoCurrencyStatus.currency.network,
address = networkAddress.defaultAddress.value,
)
val receiveAddresses = buildList {
ensName?.let { ens ->
add(
ReceiveAddressModel(
nameService = ReceiveAddressModel.NameService.Ens,
value = ens,
),
)
}
networkAddress.availableAddresses.map { address ->
add(
ReceiveAddressModel(
nameService = when (address.type) {
NetworkAddress.Address.Type.Primary -> ReceiveAddressModel.NameService.Default
NetworkAddress.Address.Type.Secondary -> ReceiveAddressModel.NameService.Legacy
},
value = address.value,
),
)
}
}
return TokenReceiveConfig(
shouldShowWarning = cryptoCurrencyStatus.currency.name !in getViewedTokenReceiveWarningUseCase(),
cryptoCurrency = cryptoCurrencyStatus.currency,
userWalletId = userWalletId,
showMemoDisclaimer = cryptoCurrencyStatus.currency.network.transactionExtrasType != Network
.TransactionExtrasType.NONE,
receiveAddress = receiveAddresses,
) )
} }