Updated on 2026-08-14
This commit is contained in:
commit
2f7c5451e6
15 changed files with 233 additions and 28 deletions
|
|
@ -120,6 +120,12 @@ sealed class AnalyticsParam {
|
|||
override val token: String,
|
||||
override val feeType: FeeType,
|
||||
) : TxSentFrom("NFT"), TxData
|
||||
|
||||
data class SendWithSwap(
|
||||
override val blockchain: String,
|
||||
override val token: String,
|
||||
override val feeType: FeeType,
|
||||
) : TxSentFrom("Send&Swap"), TxData
|
||||
}
|
||||
|
||||
sealed interface TxData {
|
||||
|
|
@ -224,5 +230,9 @@ sealed class AnalyticsParam {
|
|||
const val STANDARD = "Standard"
|
||||
const val NO_COLLECTION = "No collection"
|
||||
const val EMULATION_STATUS = "Emulation Status"
|
||||
const val SEND_TOKEN = "Send Token"
|
||||
const val RECEIVE_TOKEN = "Receive Token"
|
||||
const val SEND_BLOCKCHAIN = "Send Blockchain"
|
||||
const val RECEIVE_BLOCKCHAIN = "Receive Blockchain"
|
||||
}
|
||||
}
|
||||
|
|
@ -3,9 +3,11 @@ package com.tangem.features.send.v2.api.entity
|
|||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.features.send.v2.api.entity.FeeItem.*
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
|
|
@ -31,7 +33,19 @@ sealed class FeeSelectorUM {
|
|||
val feeExtraInfo: FeeExtraInfo,
|
||||
val feeFiatRateUM: FeeFiatRateUM?,
|
||||
val feeNonce: FeeNonce,
|
||||
) : FeeSelectorUM()
|
||||
) : FeeSelectorUM() {
|
||||
fun toAnalyticType(): AnalyticsParam.FeeType = when (fees) {
|
||||
is TransactionFee.Single -> AnalyticsParam.FeeType.Fixed
|
||||
is TransactionFee.Choosable -> when (selectedFeeItem) {
|
||||
is Suggested,
|
||||
is Custom,
|
||||
-> AnalyticsParam.FeeType.Custom
|
||||
is Fast -> AnalyticsParam.FeeType.Max
|
||||
is Market -> AnalyticsParam.FeeType.Normal
|
||||
is Slow -> AnalyticsParam.FeeType.Min
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
|
|
|||
|
|
@ -90,13 +90,15 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
|||
) { stack ->
|
||||
componentScope.launch {
|
||||
when (val activeComponent = stack.active.instance) {
|
||||
is SendConfirmComponent -> if (model.currentRoute.value.isEditMode) {
|
||||
is SendConfirmComponent -> {
|
||||
analyticsEventHandler.send(
|
||||
CommonSendAnalyticEvents.ConfirmationScreenOpened(
|
||||
categoryName = model.analyticCategoryName,
|
||||
),
|
||||
)
|
||||
activeComponent.updateState(model.uiState.value)
|
||||
if (model.currentRoute.value.isEditMode) {
|
||||
activeComponent.updateState(model.uiState.value)
|
||||
}
|
||||
}
|
||||
is SendAmountComponent -> {
|
||||
analyticsEventHandler.send(
|
||||
|
|
|
|||
|
|
@ -32,4 +32,15 @@ internal sealed class SendAnalyticEvents(
|
|||
NONCE to nonceNotEmpty.toString().capitalize(),
|
||||
),
|
||||
)
|
||||
|
||||
data class ConvertTokenButtonClicked(
|
||||
val token: String,
|
||||
val blockchain: String,
|
||||
) : SendAnalyticEvents(
|
||||
event = "Button - Convert Token",
|
||||
params = mapOf(
|
||||
TOKEN_PARAM to token,
|
||||
BLOCKCHAIN to blockchain,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -51,6 +51,7 @@ import com.tangem.features.send.v2.common.CommonSendRoute
|
|||
import com.tangem.features.send.v2.common.CommonSendRoute.*
|
||||
import com.tangem.features.send.v2.common.SendConfirmAlertFactory
|
||||
import com.tangem.features.send.v2.common.ui.state.ConfirmUM
|
||||
import com.tangem.features.send.v2.send.analytics.SendAnalyticEvents
|
||||
import com.tangem.features.send.v2.send.confirm.SendConfirmComponent
|
||||
import com.tangem.features.send.v2.send.success.SendConfirmSuccessComponent
|
||||
import com.tangem.features.send.v2.send.ui.state.SendUM
|
||||
|
|
@ -227,6 +228,12 @@ internal class SendModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onConvertToAnotherToken(lastAmount: String) {
|
||||
analyticsEventHandler.send(
|
||||
SendAnalyticEvents.ConvertTokenButtonClicked(
|
||||
token = cryptoCurrency.symbol,
|
||||
blockchain = cryptoCurrency.network.name,
|
||||
),
|
||||
)
|
||||
params.callback?.onConvertToAnotherToken(lastAmount = lastAmount)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ dependencies {
|
|||
implementation(projects.core.navigation)
|
||||
implementation(projects.core.configToggles)
|
||||
implementation(projects.core.datasource)
|
||||
implementation(projects.core.analytics)
|
||||
|
||||
/** Common */
|
||||
implementation(projects.common.ui)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ 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.activate
|
||||
import com.arkivanov.decompose.router.slot.childSlot
|
||||
import com.arkivanov.decompose.router.slot.dismiss
|
||||
import com.arkivanov.essenty.lifecycle.subscribe
|
||||
|
|
@ -69,20 +68,7 @@ internal class SwapAmountBlockComponent(
|
|||
isClickEnabled = isClickEnabled,
|
||||
onClick = onClick,
|
||||
onFinishAnimation = model::onFinishAnimation,
|
||||
onProviderSelectClick = {
|
||||
val amountUM = model.uiState.value as? SwapAmountUM.Content ?: return@SwapAmountBlockContent
|
||||
val selectedProvider = amountUM.selectedQuote.provider ?: return@SwapAmountBlockContent
|
||||
val cryptoCurrency = params.secondaryCryptoCurrency ?: return@SwapAmountBlockContent
|
||||
|
||||
model.bottomSheetNavigation.activate(
|
||||
SwapChooseProviderConfig(
|
||||
providers = amountUM.swapQuotes,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
selectedProvider = selectedProvider,
|
||||
userCountry = model.userCountry,
|
||||
),
|
||||
)
|
||||
},
|
||||
onProviderSelectClick = model::onProviderClick,
|
||||
)
|
||||
|
||||
bottomSheet.child?.instance?.BottomSheet()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package com.tangem.features.swap.v2.impl.amount.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.PROVIDER
|
||||
|
||||
internal sealed class SwapAmountAnalyticEvents(
|
||||
category: String,
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent(category = category, event = event, params = params) {
|
||||
|
||||
data class ProviderSelectorClicked(
|
||||
val categoryName: String,
|
||||
) : SwapAmountAnalyticEvents(
|
||||
category = categoryName,
|
||||
event = "Provider Clicked",
|
||||
)
|
||||
|
||||
data class ProviderChosen(
|
||||
val categoryName: String,
|
||||
val providerName: String,
|
||||
) : SwapAmountAnalyticEvents(
|
||||
category = categoryName,
|
||||
event = "Provider Chosen",
|
||||
params = mapOf(PROVIDER to providerName),
|
||||
)
|
||||
}
|
||||
|
|
@ -9,4 +9,5 @@ internal interface SwapAmountClickIntents : AmountScreenClickIntents {
|
|||
fun onInfoClick()
|
||||
fun onSelectTokenClick()
|
||||
fun onSeparatorClick()
|
||||
fun onProviderClick()
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.features.swap.v2.impl.amount.model
|
|||
|
||||
import arrow.core.getOrElse
|
||||
import com.arkivanov.decompose.router.slot.SlotNavigation
|
||||
import com.arkivanov.decompose.router.slot.activate
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.common.ui.amountScreen.converters.MaxEnterAmountConverter
|
||||
|
|
@ -10,6 +11,7 @@ import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
|
|||
import com.tangem.common.ui.navigationButtons.NavigationButton
|
||||
import com.tangem.common.ui.navigationButtons.NavigationUM
|
||||
import com.tangem.common.ui.notifications.NotificationId
|
||||
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
|
||||
|
|
@ -33,6 +35,7 @@ import com.tangem.domain.swap.usecase.GetSwapQuoteUseCase
|
|||
import com.tangem.domain.swap.usecase.SelectInitialPairUseCase
|
||||
import com.tangem.domain.tokens.GetMinimumTransactionAmountSyncUseCase
|
||||
import com.tangem.domain.transaction.usecase.GetAllowanceUseCase
|
||||
import com.tangem.features.send.v2.api.subcomponents.amount.analytics.CommonSendAmountAnalyticEvents
|
||||
import com.tangem.features.send.v2.api.subcomponents.feeSelector.FeeSelectorReloadTrigger
|
||||
import com.tangem.features.swap.v2.api.choosetoken.SwapChooseTokenNetworkListener
|
||||
import com.tangem.features.swap.v2.impl.R
|
||||
|
|
@ -40,6 +43,7 @@ import com.tangem.features.swap.v2.impl.amount.SwapAmountBlockComponent.SwapChoo
|
|||
import com.tangem.features.swap.v2.impl.amount.SwapAmountComponentParams
|
||||
import com.tangem.features.swap.v2.impl.amount.SwapAmountReduceListener
|
||||
import com.tangem.features.swap.v2.impl.amount.SwapAmountUpdateListener
|
||||
import com.tangem.features.swap.v2.impl.amount.analytics.SwapAmountAnalyticEvents
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountFieldUM
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountType
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountUM
|
||||
|
|
@ -86,6 +90,7 @@ internal class SwapAmountModel @Inject constructor(
|
|||
private val swapAmountReduceListener: SwapAmountReduceListener,
|
||||
private val feeSelectorReloadTrigger: FeeSelectorReloadTrigger,
|
||||
private val shouldShowNotificationUseCase: ShouldShowNotificationUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
) : Model(), SwapAmountClickIntents, SwapChooseProviderComponent.ModelCallback {
|
||||
|
||||
private val params: SwapAmountComponentParams = paramsContainer.require()
|
||||
|
|
@ -146,6 +151,12 @@ internal class SwapAmountModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onProviderResult(quoteUM: SwapQuoteUM) {
|
||||
analyticsEventHandler.send(
|
||||
SwapAmountAnalyticEvents.ProviderChosen(
|
||||
categoryName = params.analyticsCategoryName,
|
||||
providerName = quoteUM.provider?.name.orEmpty(),
|
||||
),
|
||||
)
|
||||
uiState.transformerUpdate(
|
||||
SwapAmountSelectQuoteTransformer(
|
||||
quoteUM = quoteUM,
|
||||
|
|
@ -201,6 +212,9 @@ internal class SwapAmountModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onMaxValueClick() {
|
||||
analyticsEventHandler.send(
|
||||
CommonSendAmountAnalyticEvents.MaxAmountButtonClicked(categoryName = params.analyticsCategoryName),
|
||||
)
|
||||
uiState.transformerUpdate(
|
||||
SwapAmountValueMaxTransformer(
|
||||
primaryMaximumAmountBoundary = primaryMaximumAmountBoundary,
|
||||
|
|
@ -221,6 +235,23 @@ internal class SwapAmountModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onAmountNext() {
|
||||
val amountState = uiState.value.swapDirection.withSwapDirection(
|
||||
onDirect = { uiState.value.primaryAmount.amountField },
|
||||
onReverse = { uiState.value.secondaryAmount.amountField },
|
||||
) as? AmountState.Data
|
||||
|
||||
amountState?.amountTextField?.isFiatValue?.let { isFiatSelected ->
|
||||
analyticsEventHandler.send(
|
||||
CommonSendAmountAnalyticEvents.SelectedCurrency(
|
||||
categoryName = params.analyticsCategoryName,
|
||||
type = if (isFiatSelected) {
|
||||
CommonSendAmountAnalyticEvents.SelectedCurrencyType.AppCurrency
|
||||
} else {
|
||||
CommonSendAmountAnalyticEvents.SelectedCurrencyType.Token
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
saveResult()
|
||||
}
|
||||
|
||||
|
|
@ -266,10 +297,30 @@ internal class SwapAmountModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onProviderClick() {
|
||||
val amountUM = uiState.value as? SwapAmountUM.Content ?: return
|
||||
val selectedProvider = amountUM.selectedQuote.provider ?: return
|
||||
val cryptoCurrency = params.secondaryCryptoCurrency ?: return
|
||||
|
||||
analyticsEventHandler.send(
|
||||
SwapAmountAnalyticEvents.ProviderSelectorClicked(
|
||||
categoryName = params.analyticsCategoryName,
|
||||
),
|
||||
)
|
||||
|
||||
bottomSheetNavigation.activate(
|
||||
SwapChooseProviderConfig(
|
||||
providers = amountUM.swapQuotes,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
selectedProvider = selectedProvider,
|
||||
userCountry = userCountry,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun confirmSendWithSwapClose() {
|
||||
val amountParams = params as? SwapAmountComponentParams.AmountParams ?: return
|
||||
val amountFieldData = uiState.value.primaryAmount.amountField as? AmountState.Data
|
||||
val callback = (params as? SwapAmountComponentParams.AmountParams)?.callback ?: return
|
||||
|
||||
val primaryCryptoCurrencyStatus = (uiState.value as? SwapAmountUM.Content)?.primaryCryptoCurrencyStatus
|
||||
if (primaryCryptoCurrencyStatus != null) {
|
||||
|
|
@ -625,7 +676,7 @@ internal class SwapAmountModel @Inject constructor(
|
|||
},
|
||||
isEnabled = state.isPrimaryButtonEnabled,
|
||||
onClick = {
|
||||
saveResult()
|
||||
onAmountNext()
|
||||
params.callback.onNextClick()
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ internal object SwapAmountClickIntentsStub : SwapAmountClickIntents {
|
|||
|
||||
override fun onSeparatorClick() {}
|
||||
|
||||
override fun onProviderClick() {}
|
||||
|
||||
override fun onAmountValueChange(value: String) {}
|
||||
|
||||
override fun onAmountPasteTriggerDismiss() {}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.arkivanov.decompose.router.stack.pop
|
|||
import com.arkivanov.decompose.value.ObserveLifecycleMode
|
||||
import com.arkivanov.decompose.value.subscribe
|
||||
import com.tangem.common.ui.navigationButtons.NavigationUM
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
|
|
@ -21,6 +22,7 @@ import com.tangem.core.ui.decompose.getEmptyComposableContentComponent
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.swap.models.R
|
||||
import com.tangem.domain.swap.models.SwapDirection
|
||||
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.DestinationRoute
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.SendDestinationComponent
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.SendDestinationComponentParams
|
||||
|
|
@ -44,6 +46,7 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
|||
@Assisted private val params: SendWithSwapComponent.Params,
|
||||
private val sendDestinationComponentFactory: SendDestinationComponent.Factory,
|
||||
private val confirmComponentFactory: SendWithSwapConfirmComponent.Factory,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
) : SendWithSwapComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val stackNavigation = StackNavigation<SendWithSwapRoute>()
|
||||
|
|
@ -80,15 +83,23 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
|||
componentScope.launch {
|
||||
when (val activeComponent = stack.active.instance) {
|
||||
is SwapAmountComponent -> {
|
||||
// todo send with swap analytics
|
||||
analyticsEventHandler.send(
|
||||
CommonSendAnalyticEvents.AmountScreenOpened(categoryName = model.analyticCategoryName),
|
||||
)
|
||||
activeComponent.updateState(model.uiState.value.amountUM)
|
||||
}
|
||||
is SendDestinationComponent -> {
|
||||
// todo send with swap analytics
|
||||
analyticsEventHandler.send(
|
||||
CommonSendAnalyticEvents.AddressScreenOpened(categoryName = model.analyticCategoryName),
|
||||
)
|
||||
activeComponent.updateState(model.uiState.value.destinationUM)
|
||||
}
|
||||
is SendWithSwapConfirmComponent -> if (model.currentRoute.value.isEditMode) {
|
||||
// todo send with swap analytics
|
||||
analyticsEventHandler.send(
|
||||
CommonSendAnalyticEvents.ConfirmationScreenOpened(
|
||||
categoryName = model.analyticCategoryName,
|
||||
),
|
||||
)
|
||||
activeComponent.updateState(model.uiState.value)
|
||||
}
|
||||
}
|
||||
|
|
@ -125,7 +136,7 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
|||
title = resourceReference(R.string.common_send),
|
||||
currentRoute = model.currentRoute.filterIsInstance<SendWithSwapRoute.Amount>(),
|
||||
isBalanceHidingFlow = model.isBalanceHiddenFlow,
|
||||
analyticsCategoryName = "",
|
||||
analyticsCategoryName = model.analyticCategoryName,
|
||||
primaryCryptoCurrencyStatusFlow = model.primaryCryptoCurrencyStatusFlow,
|
||||
secondaryCryptoCurrency = null,
|
||||
swapDirection = SwapDirection.Direct,
|
||||
|
|
@ -148,7 +159,7 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
|||
state = model.uiState.value.destinationUM,
|
||||
currentRoute = model.currentRoute.filterIsInstance<DestinationRoute>(),
|
||||
isBalanceHidingFlow = model.isBalanceHiddenFlow,
|
||||
analyticsCategoryName = "",
|
||||
analyticsCategoryName = model.analyticCategoryName,
|
||||
title = resourceReference(R.string.send_recipient_label),
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrency = secondaryCryptoCurrency,
|
||||
|
|
@ -167,7 +178,7 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
|||
appCurrency = model.appCurrency,
|
||||
userWallet = model.userWallet,
|
||||
callback = model,
|
||||
analyticsCategoryName = "",
|
||||
analyticsCategoryName = model.analyticCategoryName,
|
||||
primaryCryptoCurrencyStatusFlow = model.primaryCryptoCurrencyStatusFlow,
|
||||
primaryFeePaidCurrencyStatusFlow = model.primaryFeePaidCurrencyStatusFlow,
|
||||
swapDirection = SwapDirection.Direct,
|
||||
|
|
@ -182,7 +193,7 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
|||
sendWithSwapUMFlow = model.uiState,
|
||||
currentRoute = model.currentRoute.filterIsInstance<SendWithSwapRoute.Success>(),
|
||||
callback = model,
|
||||
analyticsCategoryName = "",
|
||||
analyticsCategoryName = model.analyticCategoryName,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
package com.tangem.features.swap.v2.impl.sendviaswap.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.PROVIDER
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.RECEIVE_BLOCKCHAIN
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.RECEIVE_TOKEN
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.SEND_BLOCKCHAIN
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.SEND_TOKEN
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
|
||||
|
||||
internal sealed class SendWithSwapAnalyticEvents(
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent(category = CommonSendAnalyticEvents.SEND_CATEGORY, event = event, params = params) {
|
||||
|
||||
data class TransactionScreenOpened(
|
||||
val providerName: String,
|
||||
val feeType: AnalyticsParam.FeeType,
|
||||
val fromToken: CryptoCurrency,
|
||||
val toToken: CryptoCurrency,
|
||||
) : SendWithSwapAnalyticEvents(
|
||||
event = "Send With Swap In Progress Screen Opened",
|
||||
params = mapOf(
|
||||
PROVIDER to providerName,
|
||||
"Commission" to if (feeType is AnalyticsParam.FeeType.Normal) "Market" else "Fast",
|
||||
SEND_TOKEN to fromToken.symbol,
|
||||
RECEIVE_TOKEN to toToken.symbol,
|
||||
SEND_BLOCKCHAIN to fromToken.network.name,
|
||||
RECEIVE_BLOCKCHAIN to toToken.network.name,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -9,6 +9,9 @@ import com.tangem.common.ui.amountScreen.converters.AmountReduceByTransformer
|
|||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.navigationButtons.NavigationButton
|
||||
import com.tangem.common.ui.navigationButtons.NavigationUM
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
|
|
@ -25,6 +28,8 @@ import com.tangem.domain.transaction.usecase.EstimateFeeUseCase
|
|||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
import com.tangem.features.send.v2.api.SendNotificationsComponent
|
||||
import com.tangem.features.send.v2.api.SendNotificationsComponent.Params.NotificationData
|
||||
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
|
||||
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents.SendScreenSource
|
||||
import com.tangem.features.send.v2.api.callbacks.FeeSelectorModelCallback
|
||||
import com.tangem.features.send.v2.api.entity.FeeSelectorUM
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationUM
|
||||
|
|
@ -43,6 +48,7 @@ import com.tangem.features.swap.v2.impl.notifications.SwapNotificationsComponent
|
|||
import com.tangem.features.swap.v2.impl.notifications.SwapNotificationsUpdateListener
|
||||
import com.tangem.features.swap.v2.impl.notifications.SwapNotificationsUpdateTrigger
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.SendWithSwapRoute
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.analytics.SendWithSwapAnalyticEvents
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.confirm.SendWithSwapConfirmComponent
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.confirm.model.transformers.SendWithSwapConfirmInitialStateTransformer
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.confirm.model.transformers.SendWithSwapConfirmationNotificationsTransformer
|
||||
|
|
@ -73,6 +79,7 @@ internal class SendWithSwapConfirmModel @Inject constructor(
|
|||
private val feeSelectorReloadTrigger: FeeSelectorReloadTrigger,
|
||||
private val swapAlertFactory: SwapAlertFactory,
|
||||
private val appRouter: AppRouter,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
swapTransactionSenderFactory: SwapTransactionSender.Factory,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model(), FeeSelectorModelCallback, SendNotificationsComponent.ModelCallback {
|
||||
|
|
@ -185,10 +192,22 @@ internal class SendWithSwapConfirmModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun showEditAmount() {
|
||||
analyticsEventHandler.send(
|
||||
CommonSendAnalyticEvents.ScreenReopened(
|
||||
categoryName = params.analyticsCategoryName,
|
||||
source = SendScreenSource.Amount,
|
||||
),
|
||||
)
|
||||
router.push(SendWithSwapRoute.Amount(isEditMode = true))
|
||||
}
|
||||
|
||||
fun showEditDestination() {
|
||||
analyticsEventHandler.send(
|
||||
CommonSendAnalyticEvents.ScreenReopened(
|
||||
categoryName = params.analyticsCategoryName,
|
||||
source = SendScreenSource.Address,
|
||||
),
|
||||
)
|
||||
router.push(SendWithSwapRoute.Destination(isEditMode = true))
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +279,7 @@ internal class SendWithSwapConfirmModel @Inject constructor(
|
|||
txHash = txHash,
|
||||
networkId = primaryCurrencyStatus.currency.network.id,
|
||||
).getOrNull().orEmpty()
|
||||
|
||||
sendSuccessAnalytics()
|
||||
uiState.update {
|
||||
it.copy(
|
||||
confirmUM = ConfirmUM.Success(
|
||||
|
|
@ -348,6 +367,33 @@ internal class SendWithSwapConfirmModel @Inject constructor(
|
|||
}.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun sendSuccessAnalytics() {
|
||||
val selectedProvider = confirmData.quote?.provider ?: return
|
||||
val fromCurrency = confirmData.fromCryptoCurrencyStatus?.currency ?: return
|
||||
val toCurrency = confirmData.toCryptoCurrencyStatus?.currency ?: return
|
||||
val feeSelectorUM = uiState.value.feeSelectorUM as? FeeSelectorUM.Content ?: return
|
||||
val feeType = feeSelectorUM.toAnalyticType()
|
||||
|
||||
analyticsEventHandler.send(
|
||||
SendWithSwapAnalyticEvents.TransactionScreenOpened(
|
||||
providerName = selectedProvider.name,
|
||||
feeType = feeType,
|
||||
fromToken = fromCurrency,
|
||||
toToken = toCurrency,
|
||||
),
|
||||
)
|
||||
analyticsEventHandler.send(
|
||||
Basic.TransactionSent(
|
||||
sentFrom = AnalyticsParam.TxSentFrom.SendWithSwap(
|
||||
blockchain = fromCurrency.network.name,
|
||||
token = fromCurrency.symbol,
|
||||
feeType = feeType,
|
||||
),
|
||||
memoType = Basic.TransactionSent.MemoType.Null,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun configConfirmNavigation() {
|
||||
combine(
|
||||
flow = uiState,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
|
|||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
|
||||
import com.tangem.features.send.v2.api.entity.FeeSelectorUM
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.SendDestinationComponent
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationUM
|
||||
|
|
@ -58,6 +59,7 @@ internal class SendWithSwapModel @Inject constructor(
|
|||
|
||||
private val params: SendWithSwapComponent.Params = paramsContainer.require()
|
||||
|
||||
val analyticCategoryName = CommonSendAnalyticEvents.SEND_CATEGORY
|
||||
val initialRoute = SendWithSwapRoute.Amount(false)
|
||||
val currentRoute = MutableStateFlow<SendWithSwapRoute>(initialRoute)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue