diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml
index 1d3513aa6e..cc96519ec8 100644
--- a/core/res/src/main/res/values-de/strings.xml
+++ b/core/res/src/main/res/values-de/strings.xml
@@ -808,6 +808,7 @@
Operation
von: %s
zu: %s
+ Validierer: %s
Versuche es erneut
Du hast dieselbe Karte gescannt. Um ein Zwillings-Wallet zu erstellen, musst du die Karte mit der Nummer %d scannen.
Du hast die falsche Doppelkarte gescannt. Bitte versuche eine andere Karte
diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml
index ecb1726923..961dbdaafb 100644
--- a/core/res/src/main/res/values-es/strings.xml
+++ b/core/res/src/main/res/values-es/strings.xml
@@ -793,7 +793,7 @@
El staking le permite ganar %1$s y obtener recompensas cada %2$s días
Gane hasta %s recompensa del staking por año
Token de %1$s en la red %%image%% %2$s
- Token en la %image% red %1$s
+ Token en la %%image%% red %1$s
El token %1$s (%2$s) es la moneda principal en la red %3$s y no se puede ocultar mientras tengas otros tokens de esta red en la lista
No se puede ocultar %s
Cambie este token por otro por una tarifa de servicio de %1$s del %2$s al %3$s de febrero.
diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt
index 3f637d2d33..249608663c 100644
--- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt
+++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt
@@ -18,6 +18,7 @@ import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull
import com.tangem.datasource.local.preferences.utils.storeObject
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.common.extensions.canHandleBlockchain
+import com.tangem.domain.common.extensions.canHandleToken
import com.tangem.domain.common.extensions.supportedBlockchains
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.common.util.derivationStyleProvider
@@ -208,6 +209,8 @@ internal class DefaultCustomTokensRepository(
blockchain = blockchain,
extraDerivationPath = null,
derivationStyleProvider = scanResponse.derivationStyleProvider,
+ )?.copy(
+ canHandleTokens = scanResponse.card.canHandleToken(blockchain, scanResponse.cardTypesResolver),
)
} else {
null
diff --git a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt
index efe1895104..2ccac4081b 100644
--- a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt
+++ b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt
@@ -50,9 +50,9 @@ import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
+import com.tangem.lib.crypto.BlockchainUtils.isSolana
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.extensions.orZero
-import com.tangem.lib.crypto.BlockchainUtils.isSolana
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -292,14 +292,18 @@ internal class DefaultStakingRepository(
) = withContext(dispatchers.io) {
if (!stakingFeatureToggle.isStakingEnabled) return@withContext
- val integrationId = integrationIdMap[getIntegrationKey(cryptoCurrency.id)] ?: return@withContext
-
- val address = walletManagersFacade.getDefaultAddress(userWalletId, cryptoCurrency.network).orEmpty()
-
cacheRegistry.invokeOnExpire(
key = getYieldBalancesKey(userWalletId),
skipCache = refresh,
block = {
+ val integrationId = integrationIdMap[getIntegrationKey(cryptoCurrency.id)]
+ val address = walletManagersFacade.getDefaultAddress(userWalletId, cryptoCurrency.network)
+
+ if (integrationId == null || address.isNullOrBlank()) {
+ cacheRegistry.invalidate(getYieldBalancesKey(userWalletId))
+ error("IntegrationId or address is null")
+ }
+
val requestBody = getBalanceRequestData(address, integrationId)
val result = stakeKitApi.getSingleYieldBalance(
integrationId = requestBody.integrationId,
@@ -307,10 +311,10 @@ internal class DefaultStakingRepository(
).getOrThrow()
stakingBalanceStore.store(
- userWalletId,
- requestBody.integrationId,
- address,
- YieldBalanceWrapperDTO(
+ userWalletId = userWalletId,
+ integrationId = requestBody.integrationId,
+ address = address,
+ item = YieldBalanceWrapperDTO(
balances = result,
integrationId = requestBody.integrationId,
addresses = requestBody.addresses,
@@ -396,7 +400,10 @@ internal class DefaultStakingRepository(
addresses.map { address -> address to integrationId }
}
.map { getBalanceRequestData(it.first.value, it.second) }
- .ifEmpty { return@invokeOnExpire }
+ .ifEmpty {
+ cacheRegistry.invalidate(getYieldBalancesKey(userWalletId))
+ error("No addresses found")
+ }
val result = stakeKitApi.getMultipleYieldBalances(availableCurrencies).getOrThrow()
stakingBalanceStore.store(userWalletId, result)
diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionType.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionType.kt
index 0c6a45bcc0..3d449ae82a 100644
--- a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionType.kt
+++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionType.kt
@@ -19,25 +19,23 @@ enum class StakingActionType {
UNKNOWN,
;
- companion object {
- val StakingActionType.asAnalyticName
- get() = when (this) {
- STAKE -> "Stake"
- UNSTAKE -> "Unstake"
- CLAIM_REWARDS -> "Claim Rewards"
- RESTAKE_REWARDS -> "Restake Rewards"
- WITHDRAW -> "Withdraw"
- RESTAKE -> "Restake"
- CLAIM_UNSTAKED -> "Claim Unstaked"
- UNLOCK_LOCKED -> "Unlock Locked"
- STAKE_LOCKED -> "Stake Locked"
- VOTE -> "Vote"
- REVOKE -> "Revoke"
- VOTE_LOCKED -> "Vote Locked"
- REVOTE -> "Revote"
- REBOND -> "Rebond"
- MIGRATE -> "Migrate"
- UNKNOWN -> "Unknown"
- }
- }
+ val asAnalyticName
+ get() = when (this) {
+ STAKE -> "Stake"
+ UNSTAKE -> "Unstake"
+ CLAIM_REWARDS -> "Claim Rewards"
+ RESTAKE_REWARDS -> "Restake Rewards"
+ WITHDRAW -> "Withdraw"
+ RESTAKE -> "Restake"
+ CLAIM_UNSTAKED -> "Claim Unstaked"
+ UNLOCK_LOCKED -> "Unlock Locked"
+ STAKE_LOCKED -> "Stake Locked"
+ VOTE -> "Vote"
+ REVOKE -> "Revoke"
+ VOTE_LOCKED -> "Vote Locked"
+ REVOTE -> "Revote"
+ REBOND -> "Rebond"
+ MIGRATE -> "Migrate"
+ UNKNOWN -> "Unknown"
+ }
}
\ No newline at end of file
diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/impl/DefaultAddCustomTokenComponent.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/impl/DefaultAddCustomTokenComponent.kt
index e9444a6d3d..563c100c5e 100644
--- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/impl/DefaultAddCustomTokenComponent.kt
+++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/impl/DefaultAddCustomTokenComponent.kt
@@ -22,6 +22,7 @@ import com.tangem.features.managetokens.entity.customtoken.CustomTokenFormValues
import com.tangem.features.managetokens.entity.customtoken.SelectedDerivationPath
import com.tangem.features.managetokens.entity.customtoken.SelectedNetwork
import com.tangem.features.managetokens.ui.AddCustomTokenBottomSheet
+import com.tangem.features.managetokens.utils.ui.toContentModel
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -34,15 +35,16 @@ internal class DefaultAddCustomTokenComponent @AssistedInject constructor(
private val analyticsEventHandler: AnalyticsEventHandler,
) : AddCustomTokenComponent, AppComponentContext by context {
+ private val initialConfiguration = AddCustomTokenConfig(
+ userWalletId = params.userWalletId,
+ step = AddCustomTokenConfig.Step.INITIAL_NETWORK_SELECTOR,
+ )
+
private val navigation = StackNavigation()
private val contentStack = childStack(
key = "add_custom_token_content_stack",
source = navigation,
- initialConfiguration = AddCustomTokenConfig(
- userWalletId = params.userWalletId,
- step = AddCustomTokenConfig.Step.INITIAL_NETWORK_SELECTOR,
- popBack = ::dismiss,
- ),
+ initialConfiguration = initialConfiguration,
handleBackButton = true,
serializer = AddCustomTokenConfig.serializer(),
childFactory = ::contentChild,
@@ -62,14 +64,14 @@ internal class DefaultAddCustomTokenComponent @AssistedInject constructor(
TangemBottomSheetConfig(
isShow = true,
onDismissRequest = ::dismiss,
- content = contentStack.active.configuration,
+ content = initialConfiguration.step.toContentModel(::popBack),
)
}
val childStack by contentStack.subscribeAsState()
AddCustomTokenBottomSheet(
config = config.copy(
- content = childStack.active.configuration,
+ content = childStack.active.configuration.step.toContentModel(::popBack),
),
content = { modifier ->
Children(
@@ -82,6 +84,17 @@ internal class DefaultAddCustomTokenComponent @AssistedInject constructor(
)
}
+ private fun popBack() {
+ when (contentStack.value.active.configuration.step) {
+ AddCustomTokenConfig.Step.INITIAL_NETWORK_SELECTOR,
+ AddCustomTokenConfig.Step.FORM,
+ -> dismiss()
+ AddCustomTokenConfig.Step.NETWORK_SELECTOR,
+ AddCustomTokenConfig.Step.DERIVATION_PATH_SELECTOR,
+ -> navigation.pop()
+ }
+ }
+
private fun contentChild(
config: AddCustomTokenConfig,
componentContext: ComponentContext,
@@ -164,7 +177,6 @@ internal class DefaultAddCustomTokenComponent @AssistedInject constructor(
val config = currentConfig.copy(
step = AddCustomTokenConfig.Step.DERIVATION_PATH_SELECTOR,
formValues = formValues,
- popBack = navigation::pop,
)
navigation.push(config)
}
@@ -175,7 +187,6 @@ internal class DefaultAddCustomTokenComponent @AssistedInject constructor(
val config = currentConfig.copy(
step = AddCustomTokenConfig.Step.NETWORK_SELECTOR,
formValues = formValues,
- popBack = navigation::pop,
)
navigation.push(config)
}
@@ -187,7 +198,6 @@ internal class DefaultAddCustomTokenComponent @AssistedInject constructor(
step = AddCustomTokenConfig.Step.FORM,
selectedNetwork = network ?: currentConfig.selectedNetwork,
selectedDerivationPath = derivationPath ?: currentConfig.selectedDerivationPath,
- popBack = ::dismiss,
)
navigation.replaceAll(config)
}
diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/preview/PreviewAddCustomTokenComponent.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/preview/PreviewAddCustomTokenComponent.kt
index 79d2f3bdcd..cfac082152 100644
--- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/preview/PreviewAddCustomTokenComponent.kt
+++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/preview/PreviewAddCustomTokenComponent.kt
@@ -9,17 +9,17 @@ import com.tangem.features.managetokens.component.AddCustomTokenComponent
import com.tangem.features.managetokens.component.CustomTokenSelectorComponent
import com.tangem.features.managetokens.entity.customtoken.AddCustomTokenConfig
import com.tangem.features.managetokens.ui.AddCustomTokenBottomSheet
+import com.tangem.features.managetokens.utils.ui.toContentModel
import kotlinx.coroutines.flow.MutableStateFlow
internal class PreviewAddCustomTokenComponent(
initialState: AddCustomTokenConfig = AddCustomTokenConfig(
userWalletId = UserWalletId(stringValue = "321"),
step = AddCustomTokenConfig.Step.INITIAL_NETWORK_SELECTOR,
- popBack = {},
),
) : AddCustomTokenComponent {
- private val previewState: MutableStateFlow = MutableStateFlow(initialState)
+ private val previewConfig: MutableStateFlow = MutableStateFlow(initialState)
override fun dismiss() {
/* no-op */
@@ -27,21 +27,21 @@ internal class PreviewAddCustomTokenComponent(
@Composable
override fun BottomSheet() {
- val state by previewState.collectAsStateWithLifecycle()
- val config = TangemBottomSheetConfig(
+ val config by previewConfig.collectAsStateWithLifecycle()
+ val bottomSheetConfig = TangemBottomSheetConfig(
isShow = true,
onDismissRequest = ::dismiss,
- content = state,
+ content = config.step.toContentModel(::dismiss),
)
AddCustomTokenBottomSheet(
- config = config,
+ config = bottomSheetConfig,
content = { modifier ->
- when (state.step) {
+ when (config.step) {
AddCustomTokenConfig.Step.INITIAL_NETWORK_SELECTOR -> {
PreviewCustomTokenSelectorComponent(
params = CustomTokenSelectorComponent.Params.NetworkSelector(
- userWalletId = state.userWalletId,
+ userWalletId = config.userWalletId,
selectedNetwork = null,
onNetworkSelected = {},
),
@@ -50,8 +50,8 @@ internal class PreviewAddCustomTokenComponent(
AddCustomTokenConfig.Step.NETWORK_SELECTOR -> {
PreviewCustomTokenSelectorComponent(
params = CustomTokenSelectorComponent.Params.NetworkSelector(
- userWalletId = state.userWalletId,
- selectedNetwork = state.selectedNetwork,
+ userWalletId = config.userWalletId,
+ selectedNetwork = config.selectedNetwork,
onNetworkSelected = {},
),
).Content(modifier)
@@ -59,9 +59,9 @@ internal class PreviewAddCustomTokenComponent(
AddCustomTokenConfig.Step.DERIVATION_PATH_SELECTOR -> {
PreviewCustomTokenSelectorComponent(
params = CustomTokenSelectorComponent.Params.DerivationPathSelector(
- userWalletId = state.userWalletId,
- selectedNetwork = state.selectedNetwork!!,
- selectedDerivationPath = state.selectedDerivationPath!!,
+ userWalletId = config.userWalletId,
+ selectedNetwork = config.selectedNetwork!!,
+ selectedDerivationPath = config.selectedDerivationPath!!,
onDerivationPathSelected = {},
),
).Content(modifier)
diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/entity/customtoken/AddCustomTokenConfig.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/entity/customtoken/AddCustomTokenConfig.kt
index 96e65e61d5..cfe7188f8a 100644
--- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/entity/customtoken/AddCustomTokenConfig.kt
+++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/entity/customtoken/AddCustomTokenConfig.kt
@@ -1,6 +1,5 @@
package com.tangem.features.managetokens.entity.customtoken
-import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.serialization.Serializable
@@ -8,12 +7,11 @@ import kotlinx.serialization.Serializable
@Serializable
internal data class AddCustomTokenConfig(
val step: Step,
- val popBack: () -> Unit,
val userWalletId: UserWalletId,
val selectedNetwork: SelectedNetwork? = null,
val selectedDerivationPath: SelectedDerivationPath? = null,
val formValues: CustomTokenFormValues = CustomTokenFormValues(),
-) : TangemBottomSheetConfigContent {
+) {
enum class Step {
INITIAL_NETWORK_SELECTOR,
diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/entity/customtoken/AddCustomTokenUM.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/entity/customtoken/AddCustomTokenUM.kt
new file mode 100644
index 0000000000..f7a59987da
--- /dev/null
+++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/entity/customtoken/AddCustomTokenUM.kt
@@ -0,0 +1,10 @@
+package com.tangem.features.managetokens.entity.customtoken
+
+import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
+import com.tangem.core.ui.extensions.TextReference
+
+internal data class AddCustomTokenUM(
+ val popBack: () -> Unit,
+ val title: TextReference,
+ val showBackButton: Boolean,
+) : TangemBottomSheetConfigContent
\ No newline at end of file
diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt
index b72993de69..3c6a9b85bf 100644
--- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt
+++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt
@@ -1,5 +1,6 @@
package com.tangem.features.managetokens.model
+import androidx.annotation.StringRes
import arrow.core.getOrElse
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
@@ -105,7 +106,7 @@ internal class ManageTokensModel @Inject constructor(
onBackButtonClick = router::pop,
),
search = SearchBarUM(
- placeholderText = resourceReference(R.string.manage_tokens_search_placeholder),
+ placeholderText = resourceReference(R.string.common_search),
query = "",
onQueryChange = ::searchCurrencies,
isActive = false,
@@ -130,7 +131,7 @@ internal class ManageTokensModel @Inject constructor(
),
),
search = SearchBarUM(
- placeholderText = resourceReference(R.string.manage_tokens_search_placeholder),
+ placeholderText = resourceReference(R.string.common_search),
query = "",
onQueryChange = ::searchCurrencies,
isActive = false,
@@ -321,8 +322,15 @@ internal class ManageTokensModel @Inject constructor(
private fun toggleSearchBar(isActive: Boolean) {
state.update { state ->
+ @StringRes val placeholderTextRes = if (isActive) {
+ R.string.manage_tokens_search_placeholder
+ } else {
+ R.string.common_search
+ }
+
state.copySealed(
search = state.search.copy(
+ placeholderText = resourceReference(placeholderTextRes),
isActive = isActive,
),
)
diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/AddCustomTokenBottomSheet.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/AddCustomTokenBottomSheet.kt
index c8fc9b7dd7..80ed6c4a56 100644
--- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/AddCustomTokenBottomSheet.kt
+++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/AddCustomTokenBottomSheet.kt
@@ -14,8 +14,6 @@ import com.tangem.core.ui.components.appbar.TangemTopAppBarHeight
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
-import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetTitle
-import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.domain.tokens.model.Network
@@ -23,13 +21,13 @@ import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.features.managetokens.component.AddCustomTokenComponent
import com.tangem.features.managetokens.component.preview.PreviewAddCustomTokenComponent
import com.tangem.features.managetokens.entity.customtoken.AddCustomTokenConfig
+import com.tangem.features.managetokens.entity.customtoken.AddCustomTokenUM
import com.tangem.features.managetokens.entity.customtoken.SelectedDerivationPath
import com.tangem.features.managetokens.entity.customtoken.SelectedNetwork
-import com.tangem.features.managetokens.impl.R
@Composable
internal fun AddCustomTokenBottomSheet(config: TangemBottomSheetConfig, content: @Composable (Modifier) -> Unit) {
- TangemBottomSheet(
+ TangemBottomSheet(
config = config,
addBottomInsets = false,
title = { model ->
@@ -47,35 +45,14 @@ internal fun AddCustomTokenBottomSheet(config: TangemBottomSheetConfig, content:
}
@Composable
-private fun Title(model: AddCustomTokenConfig, modifier: Modifier = Modifier) {
- when (model.step) {
- AddCustomTokenConfig.Step.INITIAL_NETWORK_SELECTOR,
- AddCustomTokenConfig.Step.FORM,
- -> {
- TangemBottomSheetTitle(
- modifier = modifier,
- title = resourceReference(R.string.add_custom_token_title),
- )
- }
- AddCustomTokenConfig.Step.NETWORK_SELECTOR -> {
- TangemTopAppBar(
- modifier = modifier,
- title = resourceReference(R.string.custom_token_network_selector_title),
- titleAlignment = Alignment.CenterHorizontally,
- startButton = TopAppBarButtonUM.Back(model.popBack),
- height = TangemTopAppBarHeight.BOTTOM_SHEET,
- )
- }
- AddCustomTokenConfig.Step.DERIVATION_PATH_SELECTOR -> {
- TangemTopAppBar(
- modifier = modifier,
- title = resourceReference(R.string.custom_token_derivation_path),
- titleAlignment = Alignment.CenterHorizontally,
- startButton = TopAppBarButtonUM.Back(model.popBack),
- height = TangemTopAppBarHeight.BOTTOM_SHEET,
- )
- }
- }
+private fun Title(model: AddCustomTokenUM, modifier: Modifier = Modifier) {
+ TangemTopAppBar(
+ modifier = modifier,
+ title = model.title,
+ titleAlignment = Alignment.CenterHorizontally,
+ startButton = TopAppBarButtonUM.Back(model.popBack).takeIf { model.showBackButton },
+ height = TangemTopAppBarHeight.BOTTOM_SHEET,
+ )
}
// region Preview
@@ -98,7 +75,6 @@ private class AddCustomTokenComponentPreviewProvider : PreviewParameterProvider<
initialState = AddCustomTokenConfig(
userWalletId = UserWalletId(stringValue = "321"),
step = AddCustomTokenConfig.Step.FORM,
- popBack = {},
selectedNetwork = SelectedNetwork(
id = Network.ID(value = "1"),
name = "Ethereum",
@@ -111,7 +87,6 @@ private class AddCustomTokenComponentPreviewProvider : PreviewParameterProvider<
initialState = AddCustomTokenConfig(
userWalletId = UserWalletId(stringValue = "321"),
step = AddCustomTokenConfig.Step.NETWORK_SELECTOR,
- popBack = {},
selectedNetwork = SelectedNetwork(
id = Network.ID(value = "0"),
name = "Ethereum",
@@ -124,7 +99,6 @@ private class AddCustomTokenComponentPreviewProvider : PreviewParameterProvider<
initialState = AddCustomTokenConfig(
userWalletId = UserWalletId(stringValue = "321"),
step = AddCustomTokenConfig.Step.DERIVATION_PATH_SELECTOR,
- popBack = {},
selectedDerivationPath = SelectedDerivationPath(
id = Network.ID(value = "0"),
value = Network.DerivationPath.None,
diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/ui/AddCustomTokenConfigOperations.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/ui/AddCustomTokenConfigOperations.kt
new file mode 100644
index 0000000000..8ea6f9704f
--- /dev/null
+++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/ui/AddCustomTokenConfigOperations.kt
@@ -0,0 +1,26 @@
+package com.tangem.features.managetokens.utils.ui
+
+import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.features.managetokens.entity.customtoken.AddCustomTokenConfig
+import com.tangem.features.managetokens.entity.customtoken.AddCustomTokenUM
+import com.tangem.features.managetokens.impl.R
+
+internal fun AddCustomTokenConfig.Step.toContentModel(popBack: () -> Unit): AddCustomTokenUM = when (this) {
+ AddCustomTokenConfig.Step.INITIAL_NETWORK_SELECTOR,
+ AddCustomTokenConfig.Step.FORM,
+ -> AddCustomTokenUM(
+ popBack = popBack,
+ title = resourceReference(R.string.add_custom_token_title),
+ showBackButton = false,
+ )
+ AddCustomTokenConfig.Step.NETWORK_SELECTOR -> AddCustomTokenUM(
+ popBack = popBack,
+ title = resourceReference(R.string.custom_token_network_selector_title),
+ showBackButton = true,
+ )
+ AddCustomTokenConfig.Step.DERIVATION_PATH_SELECTOR -> AddCustomTokenUM(
+ popBack = popBack,
+ title = resourceReference(R.string.custom_token_derivation_path),
+ showBackButton = true,
+ )
+}
\ No newline at end of file
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt
index 65d8c2df96..66801cb9bd 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt
@@ -7,15 +7,14 @@ import com.tangem.core.ui.event.consumedEvent
import com.tangem.core.ui.event.triggeredEvent
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.features.markets.impl.R
-import com.tangem.features.markets.tokenlist.impl.ui.state.SortByBottomSheetContentUM
-import com.tangem.features.markets.tokenlist.impl.ui.state.ListUM
-import com.tangem.features.markets.tokenlist.impl.ui.state.MarketsListItemUM
-import com.tangem.features.markets.tokenlist.impl.ui.state.MarketsListUM
-import com.tangem.features.markets.tokenlist.impl.ui.state.SortByTypeUM
+import com.tangem.features.markets.tokenlist.impl.ui.state.*
import com.tangem.utils.Provider
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
-import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.update
@Stable
internal class MarketsListUMStateManager(
@@ -193,7 +192,7 @@ internal class MarketsListUMStateManager(
private fun state(): MarketsListUM = MarketsListUM(
list = ListUM.Loading,
searchBar = SearchBarUM(
- placeholderText = resourceReference(R.string.common_search),
+ placeholderText = resourceReference(R.string.markets_search_header_title),
query = "",
onQueryChange = { searchQuery = it },
isActive = false,
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt
index 6847621b60..71d013cc58 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt
@@ -40,11 +40,11 @@ import com.tangem.features.markets.entry.BottomSheetState
import com.tangem.features.markets.impl.R
import com.tangem.features.markets.tokenlist.impl.ui.components.MarketsListLazyColumn
import com.tangem.features.markets.tokenlist.impl.ui.components.MarketsListSortByBottomSheet
+import com.tangem.features.markets.tokenlist.impl.ui.preview.MarketChartListItemPreviewDataProvider
import com.tangem.features.markets.tokenlist.impl.ui.state.ListUM
import com.tangem.features.markets.tokenlist.impl.ui.state.MarketsListUM
import com.tangem.features.markets.tokenlist.impl.ui.state.SortByBottomSheetContentUM
import com.tangem.features.markets.tokenlist.impl.ui.state.SortByTypeUM
-import com.tangem.features.markets.tokenlist.impl.ui.preview.MarketChartListItemPreviewDataProvider
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
@@ -310,7 +310,7 @@ private fun Preview() {
onItemClick = {},
),
searchBar = SearchBarUM(
- placeholderText = resourceReference(R.string.common_search),
+ placeholderText = resourceReference(R.string.markets_search_header_title),
query = "",
onQueryChange = {},
isActive = false,
diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt
index 30b7a01af8..920e6ce4cc 100644
--- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt
+++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt
@@ -3,7 +3,6 @@ package com.tangem.features.staking.impl.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.domain.staking.model.stakekit.action.StakingActionType
-import com.tangem.domain.staking.model.stakekit.action.StakingActionType.Companion.asAnalyticName
internal sealed class StakingAnalyticsEvents(
event: String,
@@ -101,6 +100,17 @@ internal sealed class StakingAnalyticsEvents(
),
)
+ data class ValidatorChosen(
+ val token: String,
+ val validator: String,
+ ) : StakingAnalyticsEvents(
+ event = "Validator Chosen",
+ params = mapOf(
+ AnalyticsParam.TOKEN_PARAM to token,
+ "Validator" to validator,
+ ),
+ )
+
data class ButtonValidator(
val source: StakeScreenSource,
val token: String,
@@ -122,11 +132,11 @@ internal sealed class StakingAnalyticsEvents(
)
data class ButtonAction(
- val action: String,
+ val action: StakingActionType,
val token: String,
val validator: String,
) : StakingAnalyticsEvents(
- event = "Button - $action",
+ event = "Button - ${action.asAnalyticName}",
params = mapOf(
AnalyticsParam.TOKEN_PARAM to token,
"Validator" to validator,
diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt
index be35fd0eaa..0b3f4fcd35 100644
--- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt
+++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt
@@ -82,14 +82,6 @@ internal class StakingAnalyticSender(
val validatorState = confirmationState?.validatorState as? ValidatorState.Content
val validatorName = validatorState?.chosenValidator?.name ?: return
- analyticsEventHandler.send(
- StakingAnalyticsEvents.ButtonAction(
- action = getStakingActionType(value).name,
- token = value.cryptoCurrencyName,
- validator = validatorName,
- ),
- )
-
analyticsEventHandler.send(
Basic.TransactionSent(
sentFrom = AnalyticsParam.TxSentFrom.Staking(
@@ -109,6 +101,20 @@ internal class StakingAnalyticSender(
)
}
+ fun sendTransactionStakingClickedAnalytics(value: StakingUiState) {
+ val confirmationState = value.confirmationState as? StakingStates.ConfirmationState.Data
+ val validatorState = confirmationState?.validatorState as? ValidatorState.Content
+ val validatorName = validatorState?.chosenValidator?.name ?: return
+
+ analyticsEventHandler.send(
+ StakingAnalyticsEvents.ButtonAction(
+ action = getStakingActionType(value),
+ token = value.cryptoCurrencySymbol,
+ validator = validatorName,
+ ),
+ )
+ }
+
private fun getStakingActionType(value: StakingUiState): StakingActionType {
val confirmationState = value.confirmationState as? StakingStates.ConfirmationState.Data
diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt
index a5afd54f97..b138f2c300 100644
--- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt
+++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt
@@ -262,7 +262,7 @@ internal class StakingViewModel @Inject constructor(
onStakingFeeError = { error ->
analyticsEventHandler.send(
StakingAnalyticsEvents.StakingError(
- value.cryptoCurrencyName,
+ value.cryptoCurrencySymbol,
error.javaClass.simpleName,
),
)
@@ -270,7 +270,7 @@ internal class StakingViewModel @Inject constructor(
updateNotifications(GetFeeError.UnknownError)
},
onFeeError = { error ->
- analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencyName))
+ analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencySymbol))
stateController.update(AddStakingErrorTransformer())
updateNotifications(error)
},
@@ -291,6 +291,7 @@ internal class StakingViewModel @Inject constructor(
private fun handleOnNextConfirmationClick() {
if (isAssentState()) {
viewModelScope.launch {
+ stakingAnalyticSender.sendTransactionStakingClickedAnalytics(value)
stateController.update(SetConfirmationStateInProgressTransformer())
transactionSender.constructAndSendTransactions(
onConstructSuccess = { constructedTransactions ->
@@ -300,7 +301,7 @@ internal class StakingViewModel @Inject constructor(
Timber.e(error.toString())
analyticsEventHandler.send(
StakingAnalyticsEvents.StakingError(
- token = value.cryptoCurrencyName,
+ token = value.cryptoCurrencySymbol,
errorType = error.javaClass.simpleName,
),
)
@@ -314,7 +315,7 @@ internal class StakingViewModel @Inject constructor(
},
onSendError = { error ->
Timber.e(error.toString())
- analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencyName))
+ analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencySymbol))
stakingEventFactory.createSendTransactionErrorAlert(error)
stateController.update(SetConfirmationStateResetAssentTransformer)
},
@@ -353,7 +354,7 @@ internal class StakingViewModel @Inject constructor(
}
override fun onInitialInfoBannerClick() {
- analyticsEventHandler.send(StakingAnalyticsEvents.WhatIsStaking(cryptoCurrencyStatus.currency.symbol))
+ analyticsEventHandler.send(StakingAnalyticsEvents.WhatIsStaking(value.cryptoCurrencySymbol))
innerRouter.openUrl(WHAT_IS_STAKING_ARTICLE_URL)
}
@@ -374,13 +375,13 @@ internal class StakingViewModel @Inject constructor(
}
override fun onMaxValueClick() {
- analyticsEventHandler.send(StakingAnalyticsEvents.ButtonMax(cryptoCurrencyStatus.currency.symbol))
+ analyticsEventHandler.send(StakingAnalyticsEvents.ButtonMax(value.cryptoCurrencySymbol))
stateController.update(AmountMaxValueStateTransformer(cryptoCurrencyStatus, yield))
}
override fun onCurrencyChangeClick(isFiat: Boolean) {
analyticsEventHandler.send(
- StakingAnalyticsEvents.AmountSelectCurrency(cryptoCurrencyStatus.currency.symbol, isFiat),
+ StakingAnalyticsEvents.AmountSelectCurrency(value.cryptoCurrencySymbol, isFiat),
)
stateController.update(AmountCurrencyChangeStateTransformer(cryptoCurrencyStatus, isFiat))
}
@@ -389,19 +390,25 @@ internal class StakingViewModel @Inject constructor(
analyticsEventHandler.send(
StakingAnalyticsEvents.ButtonValidator(
source = StakeScreenSource.Confirmation,
- token = cryptoCurrencyStatus.currency.symbol,
+ token = value.cryptoCurrencySymbol,
),
)
stakingStateRouter.showValidators()
}
override fun onValidatorSelect(validator: Yield.Validator) {
+ analyticsEventHandler.send(
+ StakingAnalyticsEvents.ValidatorChosen(
+ value.cryptoCurrencySymbol,
+ validator.name,
+ ),
+ )
stateController.update(ValidatorSelectChangeTransformer(validator))
}
override fun openRewardsValidators() {
analyticsEventHandler.send(
- StakingAnalyticsEvents.ButtonRewards(value.cryptoCurrencyName),
+ StakingAnalyticsEvents.ButtonRewards(value.cryptoCurrencySymbol),
)
val rewardsValidators =
stateController.value.rewardsValidatorsState as? StakingStates.RewardsValidatorsState.Data
@@ -412,7 +419,7 @@ internal class StakingViewModel @Inject constructor(
analyticsEventHandler.send(
StakingAnalyticsEvents.ButtonValidator(
source = StakeScreenSource.Info,
- token = cryptoCurrencyStatus.currency.symbol,
+ token = value.cryptoCurrencySymbol,
),
)
onNextClick(actionTypeToOverwrite = StakingActionCommonType.PENDING_REWARDS)
@@ -466,7 +473,7 @@ internal class StakingViewModel @Inject constructor(
analyticsEventHandler.send(
StakingAnalyticsEvents.ButtonValidator(
source = StakeScreenSource.Info,
- token = cryptoCurrencyStatus.currency.symbol,
+ token = value.cryptoCurrencySymbol,
),
)
}
@@ -511,7 +518,7 @@ internal class StakingViewModel @Inject constructor(
).fold(
ifLeft = { error ->
Timber.e(error.toString())
- analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencyName))
+ analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencySymbol))
stateController.update(
SetConfirmationStateAssentApprovalTransformer(
appCurrencyProvider = Provider { appCurrency },
@@ -533,7 +540,7 @@ internal class StakingViewModel @Inject constructor(
).fold(
ifLeft = { error ->
Timber.e(error.toString())
- analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencyName))
+ analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencySymbol))
stateController.update(
SetConfirmationStateAssentApprovalTransformer(
appCurrencyProvider = Provider { appCurrency },