From 3baec6cc7e0d15c555c61b6302fa56c774887b84 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 6 Jan 2026 17:19:24 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/di/domain/TransactionDomainModule.kt | 9 + .../token/internal/TokenFiatAmount.kt | 5 + .../components/token/state/TokenItemState.kt | 2 + .../IsGaslessFeeSupportedForNetwork.kt | 16 ++ .../send/v2/api/entity/FeeSelectorUM.kt | 1 + .../send/v2/api/params/FeeSelectorParams.kt | 4 + .../DefaultFeeSelectorBlockComponent.kt | 1 + .../DefaultFeeSelectorComponent.kt | 11 +- .../model/FeeExtendedSelectorModel.kt | 1 - .../SelectedTokenItemConverter.kt | 2 +- .../token/FeeTokenSelectorComponent.kt | 42 ++++ .../token/FeeTokenSelectorIntents.kt | 15 ++ .../token/entity/FeeTokenSelectorUM.kt | 11 + .../token/model/FeeTokenForListConverter.kt | 55 +++++ .../token/model/FeeTokenSelectorModel.kt | 93 +++++++ .../token/ui/FeeTokenSelectorContent.kt | 226 ++++++++++++++++++ .../feeselector/di/FeeSelectorModelModule.kt | 8 +- .../feeselector/model/FeeSelectorIntents.kt | 3 + .../v2/feeselector/model/FeeSelectorLogic.kt | 67 ++++-- .../v2/feeselector/model/FeeSelectorModel.kt | 15 +- .../FeeSelectorLoadedTransformer.kt | 7 + .../v2/send/confirm/SendConfirmComponent.kt | 1 + .../confirm/NFTSendConfirmComponent.kt | 1 + .../confirm/SendWithSwapConfirmComponent.kt | 1 + .../components/common/WcNavigationUtils.kt | 1 + .../send/WcSendTransactionComponent.kt | 1 + .../model/WcSendTransactionModel.kt | 3 + 27 files changed, 580 insertions(+), 22 deletions(-) create mode 100644 domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/gasless/IsGaslessFeeSupportedForNetwork.kt rename features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/{entity => model}/SelectedTokenItemConverter.kt (99%) create mode 100644 features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/FeeTokenSelectorComponent.kt create mode 100644 features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/FeeTokenSelectorIntents.kt create mode 100644 features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/entity/FeeTokenSelectorUM.kt create mode 100644 features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/model/FeeTokenForListConverter.kt create mode 100644 features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/model/FeeTokenSelectorModel.kt create mode 100644 features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/ui/FeeTokenSelectorContent.kt diff --git a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt index b7cdcf3670..ea4bd0c0da 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt @@ -17,6 +17,7 @@ import com.tangem.domain.transaction.usecase.* import com.tangem.domain.transaction.usecase.gasless.GetAvailableFeeTokensUseCase import com.tangem.domain.transaction.usecase.gasless.GetFeeForGaslessUseCase import com.tangem.domain.transaction.usecase.gasless.GetFeeForTokenUseCase +import com.tangem.domain.transaction.usecase.gasless.IsGaslessFeeSupportedForNetwork import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module @@ -323,4 +324,12 @@ internal object TransactionDomainModule { getMultiCryptoCurrencyStatusUseCase = getMultiCryptoCurrencyStatusUseCase, ) } + + @Provides + @Singleton + fun provideIsGaslessFeeSupportedForNetwork( + gaslessTransactionRepository: GaslessTransactionRepository, + ): IsGaslessFeeSupportedForNetwork { + return IsGaslessFeeSupportedForNetwork(gaslessTransactionRepository) + } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenFiatAmount.kt b/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenFiatAmount.kt index 3824de5dd7..0651618f73 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenFiatAmount.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/token/internal/TokenFiatAmount.kt @@ -2,6 +2,7 @@ package com.tangem.core.ui.components.token.internal import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -52,6 +53,10 @@ internal fun TokenFiatAmount(state: TokenFiatAmountState?, isBalanceHidden: Bool is TokenFiatAmountState.Locked -> { LockedRectangle(modifier = modifier.placeholderSize()) } + is TokenFiatAmountState.Empty -> { + // Empty box for proper measurements + Box(modifier) + } null -> Unit } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt b/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt index 72bc32e2b6..d4e8f3e33e 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/token/state/TokenItemState.kt @@ -243,6 +243,8 @@ sealed class TokenItemState { data object Loading : FiatAmountState() data object Locked : FiatAmountState() + + data object Empty : FiatAmountState() } @Immutable diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/gasless/IsGaslessFeeSupportedForNetwork.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/gasless/IsGaslessFeeSupportedForNetwork.kt new file mode 100644 index 0000000000..67c8c36205 --- /dev/null +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/gasless/IsGaslessFeeSupportedForNetwork.kt @@ -0,0 +1,16 @@ +package com.tangem.domain.transaction.usecase.gasless + +import com.tangem.domain.models.network.Network +import com.tangem.domain.transaction.GaslessTransactionRepository + +/** + * Use case to check if gasless fee is supported for a given network. + */ +class IsGaslessFeeSupportedForNetwork( + private val gaslessTransactionRepository: GaslessTransactionRepository, +) { + + operator fun invoke(network: Network): Boolean { + return gaslessTransactionRepository.isNetworkSupported(network) + } +} \ No newline at end of file diff --git a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt index 40c2047420..a62fec37f1 100644 --- a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt +++ b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt @@ -63,6 +63,7 @@ data class FeeExtraInfo( val isFeeConvertibleToFiat: Boolean, val isTronToken: Boolean, val feeCryptoCurrencyStatus: CryptoCurrencyStatus, + val availableFeeCurrencies: ImmutableList? = null, ) sealed class FeeNonce { diff --git a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/params/FeeSelectorParams.kt b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/params/FeeSelectorParams.kt index d45422c572..8e46ee3710 100644 --- a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/params/FeeSelectorParams.kt +++ b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/params/FeeSelectorParams.kt @@ -5,6 +5,7 @@ import com.tangem.blockchain.common.transaction.Fee import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.transaction.models.TransactionFeeExtended import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents @@ -13,6 +14,7 @@ import com.tangem.features.send.v2.api.entity.FeeSelectorUM sealed class FeeSelectorParams { abstract val state: FeeSelectorUM + abstract val userWalletId: UserWalletId abstract val onLoadFeeExtended: (suspend () -> Either)? abstract val onLoadFee: suspend () -> Either abstract val cryptoCurrencyStatus: CryptoCurrencyStatus @@ -24,6 +26,7 @@ sealed class FeeSelectorParams { data class FeeSelectorBlockParams( override val state: FeeSelectorUM, + override val userWalletId: UserWalletId, override val onLoadFeeExtended: (suspend () -> Either)? = null, override val onLoadFee: suspend () -> Either, override val cryptoCurrencyStatus: CryptoCurrencyStatus, @@ -36,6 +39,7 @@ sealed class FeeSelectorParams { data class FeeSelectorDetailsParams( override val state: FeeSelectorUM, + override val userWalletId: UserWalletId, override val onLoadFeeExtended: (suspend () -> Either)? = null, override val onLoadFee: suspend () -> Either, override val cryptoCurrencyStatus: CryptoCurrencyStatus, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorBlockComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorBlockComponent.kt index 8b1a940af1..bf86789265 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorBlockComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorBlockComponent.kt @@ -54,6 +54,7 @@ internal class DefaultFeeSelectorBlockComponent @AssistedInject constructor( feeDisplaySource = FeeSelectorParams.FeeDisplaySource.Screen, analyticsCategoryName = params.analyticsCategoryName, analyticsSendSource = params.analyticsSendSource, + userWalletId = params.userWalletId, ), onDismiss = { model.feeSelectorBottomSheet.dismiss() diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorComponent.kt index 5232daa424..dc62754b5c 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorComponent.kt @@ -17,6 +17,7 @@ import com.tangem.features.send.v2.api.params.FeeSelectorParams import com.tangem.features.send.v2.feeselector.component.FeeSelectorComponentParams import com.tangem.features.send.v2.feeselector.component.extended.FeeExtendedSelectorComponent import com.tangem.features.send.v2.feeselector.component.speed.FeeSpeedSelectorComponent +import com.tangem.features.send.v2.feeselector.component.token.FeeTokenSelectorComponent import com.tangem.features.send.v2.feeselector.model.FeeSelectorModel import com.tangem.features.send.v2.feeselector.route.FeeSelectorRoute import com.tangem.features.send.v2.feeselector.ui.FeeSelectorModalBottomSheet @@ -28,8 +29,9 @@ internal class DefaultFeeSelectorComponent @AssistedInject constructor( @Assisted appComponentContext: AppComponentContext, @Assisted private val params: FeeSelectorParams.FeeSelectorDetailsParams, @Assisted private val onDismiss: () -> Unit, - private val feeExtendedSelectorComponent: FeeExtendedSelectorComponent.Factory, + private val feeExtendedSelectorComponentFactory: FeeExtendedSelectorComponent.Factory, private val feeSpeedSelectorComponentFactory: FeeSpeedSelectorComponent.Factory, + private val feeTokenSelectorComponentFactory: FeeTokenSelectorComponent.Factory, ) : FeeSelectorComponent, AppComponentContext by appComponentContext { private val model: FeeSelectorModel = getOrCreateModel(params = params) @@ -86,7 +88,7 @@ internal class DefaultFeeSelectorComponent @AssistedInject constructor( ) return when (config) { - FeeSelectorRoute.NetworkFee -> feeExtendedSelectorComponent.create( + FeeSelectorRoute.NetworkFee -> feeExtendedSelectorComponentFactory.create( appComponentContext = appComponentContext, params = componentParams, ) @@ -94,7 +96,10 @@ internal class DefaultFeeSelectorComponent @AssistedInject constructor( appComponentContext = appComponentContext, params = componentParams, ) - FeeSelectorRoute.ChooseToken -> TODO() + FeeSelectorRoute.ChooseToken -> feeTokenSelectorComponentFactory.create( + appComponentContext = appComponentContext, + params = componentParams, + ) } } diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/model/FeeExtendedSelectorModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/model/FeeExtendedSelectorModel.kt index 2a8728c552..75d481da3c 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/model/FeeExtendedSelectorModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/model/FeeExtendedSelectorModel.kt @@ -11,7 +11,6 @@ import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.features.send.v2.api.entity.FeeSelectorUM import com.tangem.features.send.v2.feeselector.component.FeeSelectorComponentParams import com.tangem.features.send.v2.feeselector.component.extended.entity.FeeExtendedSelectorUM -import com.tangem.features.send.v2.feeselector.component.extended.entity.SelectedTokenItemConverter import com.tangem.features.send.v2.feeselector.route.FeeSelectorRoute import com.tangem.utils.Provider import com.tangem.utils.coroutines.CoroutineDispatcherProvider diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/entity/SelectedTokenItemConverter.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/model/SelectedTokenItemConverter.kt similarity index 99% rename from features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/entity/SelectedTokenItemConverter.kt rename to features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/model/SelectedTokenItemConverter.kt index 0959d98daf..af61ddfe05 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/entity/SelectedTokenItemConverter.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/model/SelectedTokenItemConverter.kt @@ -1,4 +1,4 @@ -package com.tangem.features.send.v2.feeselector.component.extended.entity +package com.tangem.features.send.v2.feeselector.component.extended.model import com.tangem.common.ui.tokens.TokenItemStateConverter import com.tangem.core.ui.components.icons.IconTint diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/FeeTokenSelectorComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/FeeTokenSelectorComponent.kt new file mode 100644 index 0000000000..0fc8cce54a --- /dev/null +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/FeeTokenSelectorComponent.kt @@ -0,0 +1,42 @@ +package com.tangem.features.send.v2.feeselector.component.token + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.features.send.v2.feeselector.component.FeeSelectorComponentParams +import com.tangem.features.send.v2.feeselector.component.token.model.FeeTokenSelectorModel +import com.tangem.features.send.v2.feeselector.component.token.ui.FeeTokenSelectorContent +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +internal class FeeTokenSelectorComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted private val params: FeeSelectorComponentParams, +) : AppComponentContext by appComponentContext, ComposableContentComponent { + + private val model: FeeTokenSelectorModel = getOrCreateModel(params) + + @Composable + override fun Content(modifier: Modifier) { + val state by model.uiState.collectAsStateWithLifecycle() + + FeeTokenSelectorContent( + state = state, + intents = model, + modifier = modifier, + ) + } + + @AssistedFactory + interface Factory { + fun create( + appComponentContext: AppComponentContext, + params: FeeSelectorComponentParams, + ): FeeTokenSelectorComponent + } +} \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/FeeTokenSelectorIntents.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/FeeTokenSelectorIntents.kt new file mode 100644 index 0000000000..7e9e5b99c6 --- /dev/null +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/FeeTokenSelectorIntents.kt @@ -0,0 +1,15 @@ +package com.tangem.features.send.v2.feeselector.component.token + +import androidx.compose.runtime.Stable +import com.tangem.features.send.v2.feeselector.model.FeeSelectorIntents +import com.tangem.features.send.v2.feeselector.model.StubFeeSelectorIntents + +@Stable +internal interface FeeTokenSelectorIntents : FeeSelectorIntents { + fun onLearnMoreClick() +} + +@Stable +internal class StubFeeTokenSelectorIntents : FeeTokenSelectorIntents, FeeSelectorIntents by StubFeeSelectorIntents() { + override fun onLearnMoreClick() {} +} \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/entity/FeeTokenSelectorUM.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/entity/FeeTokenSelectorUM.kt new file mode 100644 index 0000000000..5de55c5a70 --- /dev/null +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/entity/FeeTokenSelectorUM.kt @@ -0,0 +1,11 @@ +package com.tangem.features.send.v2.feeselector.component.token.entity + +import com.tangem.core.ui.components.token.state.TokenItemState +import com.tangem.features.send.v2.api.entity.FeeSelectorUM +import kotlinx.collections.immutable.ImmutableList + +data class FeeTokenSelectorUM( + val parent: FeeSelectorUM.Content, + val selectedToken: TokenItemState, + val tokens: ImmutableList, +) \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/model/FeeTokenForListConverter.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/model/FeeTokenForListConverter.kt new file mode 100644 index 0000000000..aeec5346f3 --- /dev/null +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/model/FeeTokenForListConverter.kt @@ -0,0 +1,55 @@ +package com.tangem.features.send.v2.feeselector.component.token.model + +import com.tangem.common.ui.tokens.TokenItemStateConverter +import com.tangem.core.ui.components.token.state.TokenItemState +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.format.bigdecimal.fiat +import com.tangem.core.ui.format.bigdecimal.format +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.features.send.v2.impl.R +import com.tangem.utils.Provider +import com.tangem.utils.converter.Converter + +internal class FeeTokenForListConverter( + private val appCurrencyProvider: Provider, + private val onTokenClick: () -> Unit, +) : Converter { + + override fun convert(value: CryptoCurrencyStatus): TokenItemState { + if (value.value !is CryptoCurrencyStatus.Loaded) { + return TokenItemState.Loading(id = value.currency.id.value) + } + + val appCurrency = appCurrencyProvider() + val tokenItemConverter = TokenItemStateConverter( + appCurrency = appCurrencyProvider(), + onItemClick = { _, _ -> onTokenClick() }, + ) + + val state = tokenItemConverter.convert(value) + + return when (state) { + is TokenItemState.Content -> { + val balance = value.value.fiatAmount.format { + fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol) + } + + state.copy( + fiatAmountState = TokenItemState.FiatAmountState.Empty, + subtitleState = TokenItemState.SubtitleState.TextContent( + value = resourceReference( + R.string.common_balance, + wrappedList(balance), + ), + isAvailable = false, + ), + subtitle2State = null, + + ) + } + else -> state + } + } +} \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/model/FeeTokenSelectorModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/model/FeeTokenSelectorModel.kt new file mode 100644 index 0000000000..fd5ac4c138 --- /dev/null +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/model/FeeTokenSelectorModel.kt @@ -0,0 +1,93 @@ +package com.tangem.features.send.v2.feeselector.component.token.model + +import androidx.compose.runtime.Stable +import arrow.core.getOrElse +import com.tangem.common.TangemBlogUrlBuilder +import com.tangem.core.decompose.di.ModelScoped +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.core.navigation.url.UrlOpener +import com.tangem.core.ui.components.token.state.TokenItemState +import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.features.send.v2.api.entity.FeeSelectorUM +import com.tangem.features.send.v2.feeselector.component.FeeSelectorComponentParams +import com.tangem.features.send.v2.feeselector.component.token.FeeTokenSelectorIntents +import com.tangem.features.send.v2.feeselector.component.token.entity.FeeTokenSelectorUM +import com.tangem.features.send.v2.feeselector.model.FeeSelectorIntents +import com.tangem.utils.Provider +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import javax.inject.Inject + +@Stable +@ModelScoped +internal class FeeTokenSelectorModel @Inject constructor( + paramsContainer: ParamsContainer, + override val dispatchers: CoroutineDispatcherProvider, + private val urlOpener: UrlOpener, + private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, +) : Model(), FeeTokenSelectorIntents, + FeeSelectorIntents by paramsContainer.require().intents { + + private val params = paramsContainer.require() + private var appCurrency = AppCurrency.Default + + val uiState: StateFlow + field = MutableStateFlow(getInitialState()) + + init { + initAppCurrency() + + params.state + .onEach { uiState.value = stateFromParent(it as FeeSelectorUM.Content) } + .launchIn(modelScope) + } + + private fun initAppCurrency() { + modelScope.launch { + appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default } + } + } + + private fun getInitialState(): FeeTokenSelectorUM { + val parentState = params.state.value as FeeSelectorUM.Content + return stateFromParent(parentState) + } + + private fun stateFromParent(newParentState: FeeSelectorUM.Content): FeeTokenSelectorUM { + val parentState = newParentState + val selectedCurrencyStatus = parentState.feeExtraInfo.feeCryptoCurrencyStatus + val selectedTokenUM = convertToken(selectedCurrencyStatus) + + return FeeTokenSelectorUM( + parent = parentState, + selectedToken = selectedTokenUM, + tokens = parentState.feeExtraInfo.availableFeeCurrencies?.map { status -> + convertToken(status) + }?.toImmutableList() ?: persistentListOf(selectedTokenUM), + ) + } + + private fun convertToken(status: CryptoCurrencyStatus): TokenItemState { + return FeeTokenForListConverter( + appCurrencyProvider = Provider { appCurrency }, + onTokenClick = { onTokenSelected(status) }, + ).convert(status) + } + + override fun onLearnMoreClick() { + modelScope.launch { + urlOpener.openUrl( + TangemBlogUrlBuilder.build(TangemBlogUrlBuilder.Post.WhatIsTransactionFee), + ) + } + } +} \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/ui/FeeTokenSelectorContent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/ui/FeeTokenSelectorContent.kt new file mode 100644 index 0000000000..97f3d02076 --- /dev/null +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/token/ui/FeeTokenSelectorContent.kt @@ -0,0 +1,226 @@ +package com.tangem.features.send.v2.feeselector.component.token.ui + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.key +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.text.* +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastForEach +import com.tangem.blockchain.common.Amount +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.transaction.Fee +import com.tangem.blockchain.common.transaction.TransactionFee +import com.tangem.core.ui.components.SpacerH8 +import com.tangem.core.ui.components.currency.icon.CurrencyIconState +import com.tangem.core.ui.components.token.TokenItem +import com.tangem.core.ui.components.token.state.TokenItemState +import com.tangem.core.ui.extensions.selectedBorder +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.network.Network +import com.tangem.features.send.v2.api.entity.* +import com.tangem.features.send.v2.feeselector.component.token.FeeTokenSelectorIntents +import com.tangem.features.send.v2.feeselector.component.token.StubFeeTokenSelectorIntents +import com.tangem.features.send.v2.feeselector.component.token.entity.FeeTokenSelectorUM +import com.tangem.features.send.v2.impl.R +import com.tangem.utils.StringsSigns +import kotlinx.collections.immutable.persistentListOf +import java.math.BigDecimal + +@Composable +internal fun FeeTokenSelectorContent( + state: FeeTokenSelectorUM, + intents: FeeTokenSelectorIntents, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier.padding( + bottom = 16.dp, + start = 16.dp, + end = 16.dp, + ), + ) { + Title(onLearnMoreClick = intents::onLearnMoreClick) + SpacerH8() + TokenListContent(state) + } +} + +@Composable +private fun Title(modifier: Modifier = Modifier, onLearnMoreClick: () -> Unit) { + val linkText = stringResourceSafe(R.string.common_learn_more) + val fullString = stringResourceSafe(R.string.fee_selector_choose_token_description, linkText) + val linkTextPosition = fullString.length - linkText.length + val defaultColor = TangemTheme.colors.text.secondary + val linkColor = TangemTheme.colors.text.accent + val annotatedString = remember(defaultColor, linkColor, onLearnMoreClick) { + buildAnnotatedString { + withStyle(SpanStyle(defaultColor)) { + append(fullString.substring(0, linkTextPosition)) + } + withLink( + link = LinkAnnotation.Clickable( + tag = "learn_more", + linkInteractionListener = { onLearnMoreClick() }, + ), + block = { + withStyle(SpanStyle(color = linkColor, textDecoration = TextDecoration.None)) { + append( + fullString.substring(linkTextPosition, fullString.length).replace( + ' ', + StringsSigns.NON_BREAKING_SPACE, + ), + ) + } + }, + ) + } + } + + Text( + modifier = modifier.padding(horizontal = 32.dp), + text = annotatedString, + style = TangemTheme.typography.caption2, + textAlign = TextAlign.Center, + ) +} + +@Composable +internal fun TokenListContent(state: FeeTokenSelectorUM, modifier: Modifier = Modifier) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + state.tokens.fastForEach { item -> + key(item.id) { + TokenItem( + modifier = Modifier + .selectedBorder(isSelected = state.selectedToken.id == item.id) + .clip(RoundedCornerShape(TangemTheme.dimens.radius14)) + .background(color = TangemTheme.colors.background.action), + state = item, + isBalanceHidden = false, + ) + } + } + } +} + +@Suppress("LongMethod") +@Preview +@Composable +private fun Preview() { + val cryptoCurrencyStatus = CryptoCurrencyStatus( + currency = CryptoCurrency.Coin( + id = CryptoCurrency.ID.fromValue("coin⟨BITCOIN⟩bitcoin"), + network = Network( + id = Network.ID( + value = "bitcoin", + derivationPath = Network.DerivationPath.None, + ), + backendId = "bitcoin", + name = "Bitcoin", + currencySymbol = "BTC", + derivationPath = Network.DerivationPath.None, + isTestnet = false, + standardType = Network.StandardType.Unspecified("bitcoin"), + hasFiatFeeRate = false, + canHandleTokens = false, + transactionExtrasType = Network.TransactionExtrasType.NONE, + nameResolvingType = Network.NameResolvingType.NONE, + ), + name = "Bitcoin", + symbol = "BTC", + decimals = 8, + iconUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/medium/bitcoin.png", + isCustom = false, + ), + value = CryptoCurrencyStatus.Loading, + ) + + val parentUM = FeeSelectorUM.Content( + isPrimaryButtonEnabled = false, + feeItems = persistentListOf( + FeeItem.Market( + fee = Fee.Common( + Amount( + value = BigDecimal("0.02"), + blockchain = Blockchain.Ethereum, + ), + ), + ), + ), + selectedFeeItem = FeeItem.Slow( + fee = Fee.Common( + Amount( + value = BigDecimal("0.01"), + blockchain = Blockchain.Ethereum, + ), + ), + ), + feeExtraInfo = FeeExtraInfo( + isFeeApproximate = true, + isFeeConvertibleToFiat = true, + isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, + ), + feeFiatRateUM = FeeFiatRateUM( + rate = BigDecimal.TEN, + appCurrency = AppCurrency.Default, + ), + feeNonce = FeeNonce.None, + fees = TransactionFee.Single( + Fee.Common( + Amount( + value = BigDecimal("0.01"), + blockchain = Blockchain.Ethereum, + ), + ), + ), + ) + + val tokenItemState = TokenItemState.Content( + id = "1", + iconState = CurrencyIconState.Locked, + titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Bitcoin")), + fiatAmountState = TokenItemState.FiatAmountState.Empty, + subtitle2State = null, + subtitleState = TokenItemState.SubtitleState.TextContent( + value = stringReference("Balance: 0,35853044 BTC"), + isAvailable = false, + ), + onItemClick = {}, + onItemLongClick = {}, + ) + + val state = FeeTokenSelectorUM( + parent = parentUM, + selectedToken = tokenItemState, + tokens = persistentListOf(tokenItemState, tokenItemState.copy(id = "2")), + ) + + TangemThemePreview { + FeeTokenSelectorContent( + state = state, + intents = StubFeeTokenSelectorIntents(), + modifier = Modifier + .background(TangemTheme.colors.background.tertiary), + ) + } +} \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/di/FeeSelectorModelModule.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/di/FeeSelectorModelModule.kt index 52552917e3..1891f991d3 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/di/FeeSelectorModelModule.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/di/FeeSelectorModelModule.kt @@ -5,6 +5,7 @@ import com.tangem.core.decompose.model.Model import com.tangem.features.send.v2.feeselector.component.extended.model.FeeExtendedSelectorModel import com.tangem.features.send.v2.feeselector.model.FeeSelectorBlockModel import com.tangem.features.send.v2.feeselector.component.speed.model.FeeSpeedSelectorModel +import com.tangem.features.send.v2.feeselector.component.token.model.FeeTokenSelectorModel import com.tangem.features.send.v2.feeselector.model.FeeSelectorModel import dagger.Binds import dagger.Module @@ -33,5 +34,10 @@ internal interface FeeSelectorModelModule { @Binds @IntoMap @ClassKey(FeeSpeedSelectorModel::class) - fun bindFeeSelectorSpeedModel(model: FeeSpeedSelectorModel): Model + fun bindFeeSpeedSelectorModel(model: FeeSpeedSelectorModel): Model + + @Binds + @IntoMap + @ClassKey(FeeTokenSelectorModel::class) + fun bindFeeTokenSelectorModel(model: FeeTokenSelectorModel): Model } \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorIntents.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorIntents.kt index ad255feda4..ebb0c7a91b 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorIntents.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorIntents.kt @@ -1,11 +1,13 @@ package com.tangem.features.send.v2.feeselector.model import androidx.compose.runtime.Stable +import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.features.send.v2.api.entity.FeeItem @Stable internal interface FeeSelectorIntents { fun onFeeItemSelected(feeItem: FeeItem) + fun onTokenSelected(status: CryptoCurrencyStatus) fun onCustomFeeValueChange(index: Int, value: String) fun onNonceChange(value: String) fun onDoneClick() @@ -13,6 +15,7 @@ internal interface FeeSelectorIntents { internal class StubFeeSelectorIntents : FeeSelectorIntents { override fun onFeeItemSelected(feeItem: FeeItem) {} + override fun onTokenSelected(status: CryptoCurrencyStatus) {} override fun onCustomFeeValueChange(index: Int, value: String) {} override fun onNonceChange(value: String) {} override fun onDoneClick() {} diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt index 41ba48e249..81983520fd 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt @@ -2,6 +2,7 @@ package com.tangem.features.send.v2.feeselector.model import arrow.core.Either import arrow.core.getOrElse +import arrow.core.raise.either import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.core.analytics.api.AnalyticsEventHandler @@ -12,6 +13,8 @@ import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.transaction.models.TransactionFeeExtended import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase +import com.tangem.domain.transaction.usecase.gasless.GetAvailableFeeTokensUseCase +import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.send.v2.api.SendFeatureToggles import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents.NonceInserted import com.tangem.features.send.v2.api.entity.FeeItem @@ -32,6 +35,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch @Suppress("LongParameterList") @@ -47,6 +51,8 @@ internal class FeeSelectorLogic @AssistedInject constructor( private val analyticsEventHandler: AnalyticsEventHandler, private val sendFeatureToggles: SendFeatureToggles, private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, + private val getUserWalletUseCase: GetUserWalletUseCase, + private val getAvailableFeeTokensUseCase: GetAvailableFeeTokensUseCase, ) : FeeSelectorIntents { private var appCurrency: AppCurrency = AppCurrency.Default @@ -105,6 +111,20 @@ internal class FeeSelectorLogic @AssistedInject constructor( uiState.update(FeeItemSelectedTransformer(feeItem)) } + override fun onTokenSelected(status: CryptoCurrencyStatus) { + uiState.update { state -> + if (state is FeeSelectorUM.Content) { + state.copy( + feeExtraInfo = state.feeExtraInfo.copy( + feeCryptoCurrencyStatus = status, + ), + ) + } else { + state + } + } + } + override fun onCustomFeeValueChange(index: Int, value: String) { uiState.update( FeeSelectorCustomValueChangedTransformer( @@ -208,20 +228,7 @@ internal class FeeSelectorLogic @AssistedInject constructor( } }, ifRight = { fee -> - Either.Right( - LoadedFeeResult.Extended( - fee = fee, - selectedToken = if (params.feeCryptoCurrencyStatus.currency.id != fee.feeTokenId) { - getSingleCryptoCurrencyStatusUseCase - .invokeMultiWalletSync( - userWalletId = TODO(), - cryptoCurrencyId = fee.feeTokenId, - ).getOrNull() - } else { - params.feeCryptoCurrencyStatus - }, - ), - ) + populateExtendedFee(fee) }, ) } else { @@ -229,10 +236,42 @@ internal class FeeSelectorLogic @AssistedInject constructor( } } + private suspend fun populateExtendedFee( + fee: TransactionFeeExtended, + ): Either = either { + val selectedToken = if (params.feeCryptoCurrencyStatus.currency.id != fee.feeTokenId) { + getSingleCryptoCurrencyStatusUseCase + .invokeMultiWalletSync( + userWalletId = params.userWalletId, + cryptoCurrencyId = fee.feeTokenId, + ).getOrElse { + raise(GetFeeError.DataError(IllegalStateException("No token found for id: ${fee.feeTokenId}"))) + } + } else { + params.feeCryptoCurrencyStatus + } + + val userWallet = getUserWalletUseCase(params.userWalletId).mapLeft { + GetFeeError.DataError(IllegalStateException("No wallet found for id: ${params.userWalletId}")) + }.bind() + + val availableTokens = getAvailableFeeTokensUseCase.invoke( + userWallet = userWallet, + network = params.cryptoCurrencyStatus.currency.network, + ).bind() + + LoadedFeeResult.Extended( + fee = fee, + selectedToken = selectedToken, + availableTokens = availableTokens, + ) + } + sealed class LoadedFeeResult { data class Extended( val fee: TransactionFeeExtended, val selectedToken: CryptoCurrencyStatus?, + val availableTokens: List, ) : LoadedFeeResult() data class Basic(val fee: TransactionFee) : LoadedFeeResult() diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt index 5bf01617b0..c80fac2068 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt @@ -7,6 +7,8 @@ import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.utils.stack +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.transaction.usecase.gasless.IsGaslessFeeSupportedForNetwork import com.tangem.features.send.v2.api.SendFeatureToggles import com.tangem.features.send.v2.api.entity.FeeItem import com.tangem.features.send.v2.api.entity.FeeSelectorUM @@ -24,6 +26,7 @@ internal class FeeSelectorModel @Inject constructor( feeSelectorLogicFactory: FeeSelectorLogic.Factory, override val dispatchers: CoroutineDispatcherProvider, private val sendFeatureToggles: SendFeatureToggles, + private val isGaslessFeeSupportedForNetwork: IsGaslessFeeSupportedForNetwork, ) : Model(), FeeSelectorIntents { private val params = paramsContainer.require() @@ -54,6 +57,11 @@ internal class FeeSelectorModel @Inject constructor( } } + override fun onTokenSelected(status: CryptoCurrencyStatus) { + feeSelectorLogic.onTokenSelected(status) + stackNavigation.pop() + } + override fun onCustomFeeValueChange(index: Int, value: String) { feeSelectorLogic.onCustomFeeValueChange(index, value) } @@ -85,7 +93,10 @@ internal class FeeSelectorModel @Inject constructor( return FeeSelectorRoute.ChooseSpeed } - // TODO: Add logic to choose initial route based on other conditions - return FeeSelectorRoute.NetworkFee + return if (isGaslessFeeSupportedForNetwork(params.feeCryptoCurrencyStatus.currency.network)) { + FeeSelectorRoute.NetworkFee + } else { + FeeSelectorRoute.ChooseSpeed + } } } \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorLoadedTransformer.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorLoadedTransformer.kt index 4b0668785a..75fb5135d8 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorLoadedTransformer.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorLoadedTransformer.kt @@ -11,6 +11,7 @@ import com.tangem.features.send.v2.feeselector.model.FeeSelectorLogic.LoadedFeeR import com.tangem.lib.crypto.BlockchainUtils.isTron import com.tangem.utils.transformer.Transformer import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList @Suppress("LongParameterList") internal class FeeSelectorLoadedTransformer( @@ -61,6 +62,7 @@ internal class FeeSelectorLoadedTransformer( isTronToken = cryptoCurrencyStatus.currency is CryptoCurrency.Token && isTron(cryptoCurrencyStatus.currency.network.rawId), feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, + availableFeeCurrencies = getAvailableFeeCurrencies(), ), feeFiatRateUM = feeCryptoCurrencyStatus.value.fiatRate?.let { rate -> FeeFiatRateUM( @@ -78,4 +80,9 @@ internal class FeeSelectorLoadedTransformer( }, ) } + + private fun getAvailableFeeCurrencies(): ImmutableList? { + if (fees !is LoadedFeeResult.Extended) return null + return fees.availableTokens.toImmutableList() + } } \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/SendConfirmComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/SendConfirmComponent.kt index 02c4c88993..fef494deef 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/SendConfirmComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/SendConfirmComponent.kt @@ -92,6 +92,7 @@ internal class SendConfirmComponent( feeDisplaySource = FeeSelectorParams.FeeDisplaySource.Screen, analyticsCategoryName = params.analyticsCategoryName, analyticsSendSource = params.analyticsSendSource, + userWalletId = params.userWallet.walletId, ), onResult = model::onFeeResult, ) diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/NFTSendConfirmComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/NFTSendConfirmComponent.kt index 8bf26ce732..fec1c74cb7 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/NFTSendConfirmComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/NFTSendConfirmComponent.kt @@ -78,6 +78,7 @@ internal class NFTSendConfirmComponent @AssistedInject constructor( feeDisplaySource = FeeSelectorParams.FeeDisplaySource.Screen, analyticsCategoryName = params.analyticsCategoryName, analyticsSendSource = params.analyticsSendSource, + userWalletId = params.userWallet.walletId, ), onResult = model::onFeeResult, ) diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/SendWithSwapConfirmComponent.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/SendWithSwapConfirmComponent.kt index 0b4b6b742e..dc79a0ee29 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/SendWithSwapConfirmComponent.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/SendWithSwapConfirmComponent.kt @@ -96,6 +96,7 @@ internal class SendWithSwapConfirmComponent @AssistedInject constructor( feeDisplaySource = FeeDisplaySource.Screen, analyticsCategoryName = params.analyticsCategoryName, analyticsSendSource = params.analyticsSendSource, + userWalletId = params.userWallet.walletId, ), onResult = model::onFeeResult, ) diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/common/WcNavigationUtils.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/common/WcNavigationUtils.kt index eaf30bde46..d4686d0460 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/common/WcNavigationUtils.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/common/WcNavigationUtils.kt @@ -57,6 +57,7 @@ internal fun getWcCommonScreen( feeDisplaySource = FeeDisplaySource.BottomSheet, analyticsCategoryName = WcAnalyticEvents.WC_CATEGORY_NAME, analyticsSendSource = CommonSendAnalyticEvents.CommonSendSource.WalletConnect, + userWalletId = model.userWallet.walletId, ), ) } diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/send/WcSendTransactionComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/send/WcSendTransactionComponent.kt index abb3dcce53..cf234d50b6 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/send/WcSendTransactionComponent.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/send/WcSendTransactionComponent.kt @@ -76,6 +76,7 @@ internal class WcSendTransactionComponent( feeDisplaySource = FeeSelectorParams.FeeDisplaySource.BottomSheet, analyticsCategoryName = WcAnalyticEvents.WC_CATEGORY_NAME, analyticsSendSource = CommonSendAnalyticEvents.CommonSendSource.WalletConnect, + userWalletId = model.userWallet.walletId, ), onResult = model::updateFee, ) diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt index d305e4a233..f02eb11f51 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt @@ -105,6 +105,9 @@ internal class WcSendTransactionModel @Inject constructor( private val securityStatusState = MutableStateFlow>(Lce.Loading(partialContent = null)) + val userWallet + get() = useCase.wallet + init { @Suppress("UnusedPrivateMember") modelScope.launch {