From 5a5cfc0facf83355624cd155ffb60e21ae567b95 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 25 Apr 2025 19:51:03 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../core/analytics/models/AnalyticsParam.kt | 6 ++ core/res/src/main/res/values-de/strings.xml | 2 +- core/res/src/main/res/values-es/strings.xml | 2 +- core/res/src/main/res/values-fr/strings.xml | 2 +- core/res/src/main/res/values-it/strings.xml | 6 -- core/res/src/main/res/values-ja/strings.xml | 8 +- core/res/src/main/res/values-ru/strings.xml | 3 + .../src/main/res/values-uk-rUA/strings.xml | 2 +- .../src/main/res/values-zh-rTW/strings.xml | 3 - core/res/src/main/res/values/strings.xml | 4 + .../v2/sendnft/DefaultNFTSendComponent.kt | 25 ++++-- .../analytics/NFTSendAnalyticEvents.kt | 28 ++++++ .../analytics/NFTSendAnalyticHelper.kt | 53 +++++++++++ .../confirm/model/NFTSendConfirmModel.kt | 89 +++++++++++++++---- ...endConfirmationNotificationsTransformer.kt | 8 +- .../send/v2/sendnft/model/NFTSendModel.kt | 38 +++++++- 16 files changed, 232 insertions(+), 47 deletions(-) create mode 100644 features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/analytics/NFTSendAnalyticEvents.kt create mode 100644 features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/analytics/NFTSendAnalyticHelper.kt diff --git a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt index 31e79f809c..26da2b1161 100644 --- a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt +++ b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt @@ -113,6 +113,12 @@ sealed class AnalyticsParam { data object WalletConnect : TxSentFrom("WalletConnect") data object Sell : TxSentFrom("Sell") + + data class NFT( + override val blockchain: String, + override val token: String, + override val feeType: FeeType, + ) : TxSentFrom("NFT"), TxData } sealed interface TxData { diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index 67aa4da4df..cecd9a6bbb 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -379,7 +379,7 @@ Du hast deine biometrischen Daten aktualisiert, scanne deine Karte oder Ring, um einzutreten Dein Guthaben sollte höher sein als der Gebührenwert, um eine Überweisung zu tätigen Unzureichende Mittel - Du hast nicht genug Mana für diese Transaktion. Bitte warte, bis das Mana wieder aufgefüllt ist. Dein Mana-Guthaben beträgt %1$s/%2$s + Du hast nicht genug Mana für diese Transaktion. Bitte warte, bis das Mana wieder aufgefüllt ist. Dein Managuthaben beträgt %1$s/%2$s Nicht genug Mana Du kannst nur %s übertragen, da das Koinos-Netzwerk ein Mana-Limit vorgibt. Mana-Limit diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml index 8d8cd1ccfe..128949fd13 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -375,7 +375,7 @@ Ha actualizado la biometría, escanee su tarjeta o anillo para entrar Su saldo debe ser mayor que el valor de la tarifa para hacer una transferencia Saldo insuficiente - No tiene suficiente Mana para esta transacción. Por favor, espere hasta que el Mana se recargue. Su saldo de Mana es %1$s/%2$s + No tiene suficiente Mana para esta transacción. Espere hasta que se reponga el maná. Su saldo de maná es %1$s/%2$s Mana insuficiente Solo puede transferir %s debido al límite de Mana impuesto por la red Koinos Límite de Mana diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index e7209c6305..9d695df7c1 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -375,7 +375,7 @@ Vous avez mis à jour vos données biométriques, scannez votre carte ou bague pour entrer Votre solde doit être supérieur à la valeur des frais pour effectuer un transfert Solde insuffisant - Vous n\'avez pas assez de Mana pour cette transaction. Veuillez attendre que le Mana soit reconstitué. Votre solde de Mana est de %1$s/%2$s + Vous n\'avez pas assez de mana pour cette transaction. Veuillez patienter jusqu\'à ce que le mana soit réapprovisionné. Votre solde de mana est %1$s/%2$s Mana insuffisant Vous ne pouvez transférer que %s en raison de la limite de Mana imposée par le réseau Koinos Limite de Mana diff --git a/core/res/src/main/res/values-it/strings.xml b/core/res/src/main/res/values-it/strings.xml index 001ae1f84d..7132029cfe 100644 --- a/core/res/src/main/res/values-it/strings.xml +++ b/core/res/src/main/res/values-it/strings.xml @@ -19,7 +19,6 @@ Invia Impossibile inviare la transazione Con successo - Due to %1$s limitations only %2$d UTXOs can fit in a single transaction. This means you can only send %3$s or less. You need to reduce the amount. Codice di accesso Prima di scansionare la carta sarà necessario inserire il codice di accesso corretto Mantenimento della carta @@ -36,7 +35,6 @@ Termini del servizio Not enough funds for the transaction. Please top up your account. An error occurred - An error occurred. Code: %s. Notifica richiesta Scansiona carta Avvicina per modificare il codice di accesso @@ -44,9 +42,6 @@ Avvicina per scansionare Avvicina per firmare Avvicina la carta - You don\'t have enough Mana for this transaction. Please wait until the Mana is refilled. Your Mana balance is %1$s/%2$s - To use the %1$s network, you must pay the account reserve (%2$s %3$s), which locks up and hides that amount indefinitely - Destination account is not active. Send %s or more to activate the account. Per creare un account, invia fondi a questo indirizzo The destination account does not have a trustline for the asset being sent. Crea portafoglio @@ -55,7 +50,6 @@ L\'importo minimo è di %s Il resto minimo è di %s Commissione non valida - Minimum balance is %s Il conto totale non è stato creato L\'importo da inviare deve essere %s + commissione o maggiore Errore sconosciuto Memo diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index ec498830f5..e41ea53407 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -377,7 +377,7 @@ 生体認証を更新しました。カードまたはリングをスキャンして入ってください。 送金するには、残高が手数料額より高くなければなりません。 残高不足 - この取引に必要なManaが不足しています。Manaが補充されるまでお待ちください。あなたのMana残高は%1$s/%2$sです。 + この取引に必要なManaが足りません。Manaが補充されるまでお待ちください。Manaの残高は%1$s / %2$sです。 Manaが不足しています KoinosネットワークによるMana制限のため、%s のみ送金できます。 Mana上限 @@ -548,6 +548,8 @@ 送信先アカウントが有効ではありません。%s 以上を送信してアカウントを有効にしてください。 アカウントを作成するには、このアドレスに資金を送金してください 送信先アカウントには、送金されるアセットのトラストラインがありません。 + コードを共有すると、販売ごとに5 USDTを獲得できます。お友達は10%割引になります。 + 友達への紹介で報酬を獲得しよう! すべてのデバイスを保護するには、単一のアクセスコードを設定してください。 保護する 後で各カードおよびリングに個別のアクセスコードを設定できます。 @@ -892,9 +894,9 @@ 再ステーキングを使うと、ステーキングを解除することなく、あるバリデータから別のバリデータに資金を移動できます。 残高のすべてをステーキングしようとしています。ステーキング解除や報酬請求にかかるネットワーク手数料をカバーするために、少額を残しておくことをお勧めします。 TONでステーキングを開始するには、まず任意の金額の送金を行ってください。これにより、ウォレットがアクティブになります。 - TONをステーキングまたは出金する場合、入金と出金の両方でステーキング額から0.2 TONの手数料が差し引かれます。 + ネットワーク手数料に加え、取引の全ステップを完了するには最大0.2 TONが必要です。未使用分は取引完了後に返金されます。 この操作を続行するには、ネットワーク手数料に加えて0.2 TONが必要です。残高を補充してください。 - ステーキング手数料 + 0.2 TON保留済み このアクションは、ネットワークのルールに従って、他のポジションをクローズするか、引き出しステータスに切り替えます。 ポジション状況 資金をステーキングから引き出すには、ロックを解除してください。ロック解除には%sかかります。 diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 401b2fea2a..c599f5bead 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -525,6 +525,9 @@ Аккаунт получателя не активирован. Отправьте %s или более для активации аккаунта. Для создания аккаунта отправьте средства на этот адрес Аккаунт получателя не содержит трастлайна для отправляемого актива. + Присоединиться + Поделись промокодом — заработай 5 USDT с каждой покупки. Твои друзья получат скидку 10% на карту Tangem! + Получай бонусы за каждого друга! Установите единый код доступа для защиты всех ваших карт или колец Защита Установите индивидуальный код доступа для каждой карты или кольца позже. diff --git a/core/res/src/main/res/values-uk-rUA/strings.xml b/core/res/src/main/res/values-uk-rUA/strings.xml index 1a942a7a26..130fc7559d 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -381,7 +381,7 @@ Ви оновили дані біометрії, відскануйте свою картку або кільце для входу Ваш баланс повинен перевищувати суму комісії для здійснення переказу Недостатньо балансу - У вас недостатньо Mana для цієї транзакції. Будь ласка, зачекайте, поки Mana буде поповнена. Ваш баланс Mana становить %1$s/%2$s + У вас недостатньо Мани для цієї транзакції. Будь ласка, зачекайте, поки Мана поповниться. Ваш баланс мани дорівнює %1$s/%2$s Недостатньо Mana Ви можете переказати тільки %s через обмеження Mana, встановлене мережею Koinos Ліміт Mana diff --git a/core/res/src/main/res/values-zh-rTW/strings.xml b/core/res/src/main/res/values-zh-rTW/strings.xml index 78849a3497..e1f37d9840 100644 --- a/core/res/src/main/res/values-zh-rTW/strings.xml +++ b/core/res/src/main/res/values-zh-rTW/strings.xml @@ -140,7 +140,6 @@ Tangem反饋 無法發送交易 An error occurred - An error occurred. Code: %s. 需要memo 數量 %s 要繼續,您需要允許 %1s 智能合約使用您的 %2s @@ -153,12 +152,10 @@ 點擊簽名 點按卡片 您已更新生物識別登入,掃描您的卡進入 - You don\'t have enough Mana for this transaction. Please wait until the Mana is refilled. Your Mana balance is %1$s/%2$s 管理代幣 要訪問所有的網路您需要掃描卡片 掃描卡片 代幣 - To use the %1$s network, you must pay the account reserve (%2$s %3$s), which locks up and hides that amount indefinitely 目標帳戶未激活。發送 %s 或更多以激活帳戶 要創建帳戶,請將資金發送到此地址 目標帳戶沒有用於發送資產的 trustline diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 90a9ac6c99..9e12a259c0 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -546,6 +546,7 @@ You haven\'t added this network yet. To start receiving NFTs, add it to the main screen! Network not added Not Added + Send NFT Traits %1$d NFTs in %2$d collection Tap here to receive first NFT @@ -555,6 +556,9 @@ Destination account is not active. Send %s or more to activate the account. To create account send funds to this address The destination account does not have a trustline for the asset being sent. + Join Now + Share your code - earn 5 USDT per sale. Your friend gets 10% OFF. + Get REWARDS for every friend! Set up a single access code to protect all your devices. Protect Set an individual access code for each card or ring later. diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt index 4b65d6d5ae..7fc4f402c2 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt @@ -11,16 +11,20 @@ import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.router.stack.pop import com.arkivanov.decompose.value.ObserveLifecycleMode import com.arkivanov.decompose.value.subscribe +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 import com.tangem.core.decompose.navigation.inner.InnerRouter import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.core.ui.extensions.resourceReference import com.tangem.features.nft.component.NFTDetailsBlockComponent import com.tangem.features.send.v2.api.NFTSendComponent import com.tangem.features.send.v2.common.CommonSendRoute +import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents import com.tangem.features.send.v2.common.ui.SendContent import com.tangem.features.send.v2.common.ui.state.ConfirmUM +import com.tangem.features.send.v2.impl.R import com.tangem.features.send.v2.sendnft.confirm.NFTSendConfirmComponent import com.tangem.features.send.v2.sendnft.model.NFTSendModel import com.tangem.features.send.v2.subcomponents.destination.SendDestinationComponent @@ -40,9 +44,11 @@ internal class DefaultNFTSendComponent @AssistedInject constructor( @Assisted appComponentContext: AppComponentContext, @Assisted private val params: NFTSendComponent.Params, private val nftDetailsBlockComponentFactory: NFTDetailsBlockComponent.Factory, + private val analyticsEventHandler: AnalyticsEventHandler, ) : NFTSendComponent, AppComponentContext by appComponentContext { private val stackNavigation = StackNavigation() + private val analyticsCategoryName = CommonSendAnalyticEvents.NFT_SEND_CATEGORY private val innerRouter = InnerRouter( stackNavigation = stackNavigation, @@ -79,15 +85,21 @@ internal class DefaultNFTSendComponent @AssistedInject constructor( componentScope.launch { when (val activeComponent = stack.active.instance) { is NFTSendConfirmComponent -> if (currentRouteFlow.value.isEditMode) { - // analyticsEventHandler.send(SendAnalyticEvents.ConfirmationScreenOpened) + analyticsEventHandler.send( + CommonSendAnalyticEvents.ConfirmationScreenOpened(categoryName = analyticsCategoryName), + ) activeComponent.updateState(model.uiState.value) } is SendDestinationComponent -> { - // analyticsEventHandler.send(SendAnalyticEvents.AddressScreenOpened) + analyticsEventHandler.send( + CommonSendAnalyticEvents.AddressScreenOpened(categoryName = analyticsCategoryName), + ) activeComponent.updateState(model.uiState.value.destinationUM) } is SendFeeComponent -> { - // analyticsEventHandler.send(SendAnalyticEvents.FeeScreenOpened) + analyticsEventHandler.send( + CommonSendAnalyticEvents.FeeScreenOpened(categoryName = analyticsCategoryName), + ) } } currentRouteFlow.emit(stack.active.configuration) @@ -121,7 +133,8 @@ internal class DefaultNFTSendComponent @AssistedInject constructor( state = model.uiState.value.destinationUM, currentRoute = currentRouteFlow.filterIsInstance(), isBalanceHidingFlow = model.isBalanceHiddenFlow, - analyticsCategoryName = "", // todo + title = resourceReference(R.string.nft_send), + analyticsCategoryName = analyticsCategoryName, userWalletId = params.userWalletId, cryptoCurrency = model.cryptoCurrency, callback = model, @@ -145,7 +158,7 @@ internal class DefaultNFTSendComponent @AssistedInject constructor( params = SendFeeComponentParams.FeeParams( state = model.uiState.value.feeUM, currentRoute = currentRouteFlow.filterIsInstance(), - analyticsCategoryName = "", // todo + analyticsCategoryName = analyticsCategoryName, userWallet = model.userWallet, cryptoCurrencyStatus = model.cryptoCurrencyStatus, feeCryptoCurrencyStatus = model.feeCryptoCurrencyStatus, @@ -167,7 +180,7 @@ internal class DefaultNFTSendComponent @AssistedInject constructor( nftDetailsBlockComponentFactory = nftDetailsBlockComponentFactory, params = NFTSendConfirmComponent.Params( state = model.uiState.value, - analyticsCategoryName = "", // todo + analyticsCategoryName = analyticsCategoryName, userWallet = model.userWallet, nftAsset = params.nftAsset, nftCollectionName = params.nftCollectionName, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/analytics/NFTSendAnalyticEvents.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/analytics/NFTSendAnalyticEvents.kt new file mode 100644 index 0000000000..ec215b0478 --- /dev/null +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/analytics/NFTSendAnalyticEvents.kt @@ -0,0 +1,28 @@ +package com.tangem.features.send.v2.sendnft.analytics + +import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.analytics.models.AnalyticsParam.Key.FEE_TYPE +import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM +import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents + +/** + * Send screen analytics + */ +internal sealed class NFTSendAnalyticEvents( + event: String, + params: Map = mapOf(), +) : AnalyticsEvent(category = CommonSendAnalyticEvents.NFT_SEND_CATEGORY, event = event, params = params) { + + /** Transaction send screen opened */ + data class TransactionScreenOpened( + val token: String, + val feeType: AnalyticsParam.FeeType, + ) : NFTSendAnalyticEvents( + event = "NFT Sent Screen Opened", + params = mapOf( + TOKEN_PARAM to token, + FEE_TYPE to feeType.value, + ), + ) +} \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/analytics/NFTSendAnalyticHelper.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/analytics/NFTSendAnalyticHelper.kt new file mode 100644 index 0000000000..da36ab5006 --- /dev/null +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/analytics/NFTSendAnalyticHelper.kt @@ -0,0 +1,53 @@ +package com.tangem.features.send.v2.sendnft.analytics + +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.domain.tokens.model.CryptoCurrency +import com.tangem.features.send.v2.sendnft.ui.state.NFTSendUM +import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationTextFieldUM +import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM +import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeSelectorUM +import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeUM +import javax.inject.Inject + +@ModelScoped +internal class NFTSendAnalyticHelper @Inject constructor( + private val analyticsEventHandler: AnalyticsEventHandler, +) { + + fun nftSendSuccessAnalytics(cryptoCurrency: CryptoCurrency, nftSendUM: NFTSendUM) { + val destinationUM = nftSendUM.destinationUM as? DestinationUM.Content + val feeUM = nftSendUM.feeUM as? FeeUM.Content + val feeSelectorUM = feeUM?.feeSelectorUM as? FeeSelectorUM.Content ?: return + val feeType = feeSelectorUM.selectedType.toAnalyticType(feeSelectorUM) + analyticsEventHandler.send( + NFTSendAnalyticEvents.TransactionScreenOpened( + token = cryptoCurrency.symbol, + feeType = feeType, + ), + ) + analyticsEventHandler.send( + Basic.TransactionSent( + sentFrom = AnalyticsParam.TxSentFrom.NFT( + blockchain = cryptoCurrency.network.name, + token = cryptoCurrency.symbol, + feeType = feeType, + ), + memoType = getSendTransactionMemoType(destinationUM?.memoTextField), + ), + ) + } + + private fun getSendTransactionMemoType( + recipientMemo: DestinationTextFieldUM.RecipientMemo?, + ): Basic.TransactionSent.MemoType { + val memo = recipientMemo?.value + return when { + memo?.isBlank() == true -> Basic.TransactionSent.MemoType.Empty + memo?.isNotBlank() == true -> Basic.TransactionSent.MemoType.Full + else -> Basic.TransactionSent.MemoType.Null + } + } +} \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/NFTSendConfirmModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/NFTSendConfirmModel.kt index 19424360b9..0e89448a8f 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/NFTSendConfirmModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/NFTSendConfirmModel.kt @@ -14,6 +14,11 @@ import com.tangem.core.navigation.url.UrlOpener import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.datasource.local.nft.converter.NFTSdkAssetConverter +import com.tangem.domain.feedback.GetCardInfoUseCase +import com.tangem.domain.feedback.SaveBlockchainErrorUseCase +import com.tangem.domain.feedback.SendFeedbackEmailUseCase +import com.tangem.domain.feedback.models.BlockchainErrorInfo +import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.settings.IsSendTapHelpEnabledUseCase import com.tangem.domain.settings.NeverShowTapHelpUseCase import com.tangem.domain.transaction.usecase.CreateNFTTransferTransactionUseCase @@ -21,12 +26,14 @@ import com.tangem.domain.transaction.usecase.SendTransactionUseCase import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase import com.tangem.features.send.v2.common.CommonSendRoute import com.tangem.features.send.v2.common.SendBalanceUpdater +import com.tangem.features.send.v2.common.SendConfirmAlertFactory +import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents +import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents.SendScreenSource import com.tangem.features.send.v2.common.ui.state.ConfirmUM import com.tangem.features.send.v2.common.ui.state.NavigationUM import com.tangem.features.send.v2.impl.R -import com.tangem.features.send.v2.send.analytics.SendAnalyticEvents -import com.tangem.features.send.v2.send.analytics.SendAnalyticEvents.SendScreenSource import com.tangem.features.send.v2.send.ui.state.ButtonsUM +import com.tangem.features.send.v2.sendnft.analytics.NFTSendAnalyticHelper import com.tangem.features.send.v2.sendnft.confirm.NFTSendConfirmComponent import com.tangem.features.send.v2.sendnft.confirm.model.transformers.NFTSendConfirmInitialStateTransformer import com.tangem.features.send.v2.sendnft.confirm.model.transformers.NFTSendConfirmSendingStateTransformer @@ -40,6 +47,7 @@ import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeUM import com.tangem.features.send.v2.subcomponents.notifications.NotificationsUpdateTrigger import com.tangem.features.send.v2.subcomponents.notifications.model.NotificationData import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.extensions.stripZeroPlainString import com.tangem.utils.transformer.update import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch @@ -47,7 +55,7 @@ import timber.log.Timber import java.math.BigDecimal import javax.inject.Inject -@Suppress("LongParameterList") +@Suppress("LongParameterList", "LargeClass") @ModelScoped internal class NFTSendConfirmModel @Inject constructor( paramsContainer: ParamsContainer, @@ -59,17 +67,23 @@ internal class NFTSendConfirmModel @Inject constructor( private val createNFTTransferTransactionUseCase: CreateNFTTransferTransactionUseCase, private val sendTransactionUseCase: SendTransactionUseCase, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, + private val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase, + private val getCardInfoUseCase: GetCardInfoUseCase, + private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, private val notificationsUpdateTrigger: NotificationsUpdateTrigger, private val sendFeeCheckReloadTrigger: SendFeeCheckReloadTrigger, private val sendFeeCheckReloadListener: SendFeeCheckReloadListener, + private val alertFactory: SendConfirmAlertFactory, private val urlOpener: UrlOpener, private val shareManager: ShareManager, private val analyticsEventHandler: AnalyticsEventHandler, + private val nftSendAnalyticHelper: NFTSendAnalyticHelper, sendBalanceUpdaterFactory: SendBalanceUpdater.Factory, ) : Model(), NFTSendConfirmClickIntents { private val params: NFTSendConfirmComponent.Params = paramsContainer.require() + private val analyticsCategoryName = params.analyticsCategoryName private val userWallet = params.userWallet private val cryptoCurrencyStatus = params.cryptoCurrencyStatus private val cryptoCurrency = cryptoCurrencyStatus.currency @@ -129,7 +143,12 @@ internal class NFTSendConfirmModel @Inject constructor( val confirmUM = it.confirmUM as? ConfirmUM.Content it.copy(confirmUM = confirmUM?.copy(showTapHelp = false) ?: it.confirmUM) } - // analyticsEventHandler.send(SendAnalyticEvents.ScreenReopened(SendScreenSource.Address)) + analyticsEventHandler.send( + CommonSendAnalyticEvents.ScreenReopened( + categoryName = analyticsCategoryName, + source = SendScreenSource.Address, + ), + ) router.push(CommonSendRoute.Destination(isEditMode = true)) } } @@ -141,7 +160,12 @@ internal class NFTSendConfirmModel @Inject constructor( val confirmUM = it.confirmUM as? ConfirmUM.Content it.copy(confirmUM = confirmUM?.copy(showTapHelp = false) ?: it.confirmUM) } - // analyticsEventHandler.send(SendAnalyticEvents.ScreenReopened(SendScreenSource.Fee)) + analyticsEventHandler.send( + CommonSendAnalyticEvents.ScreenReopened( + categoryName = analyticsCategoryName, + source = SendScreenSource.Fee, + ), + ) router.push(CommonSendRoute.Fee) } } @@ -159,18 +183,38 @@ internal class NFTSendConfirmModel @Inject constructor( override fun onExploreClick() { val confirmUM = uiState.value.confirmUM as? ConfirmUM.Success ?: return - // analyticsEventHandler.send(SendAnalyticEvents.ExploreButtonClicked) + analyticsEventHandler.send( + CommonSendAnalyticEvents.ExploreButtonClicked(analyticsCategoryName), + ) urlOpener.openUrl(confirmUM.txUrl) } override fun onShareClick() { val confirmUM = uiState.value.confirmUM as? ConfirmUM.Success ?: return - // analyticsEventHandler.send(SendAnalyticEvents.ShareButtonClicked) + analyticsEventHandler.send( + CommonSendAnalyticEvents.ShareButtonClicked(analyticsCategoryName), + ) shareManager.shareText(confirmUM.txUrl) } override fun onFailedTxEmailClick(errorMessage: String) { - // TODO() + saveBlockchainErrorUseCase( + error = BlockchainErrorInfo( + errorMessage = errorMessage, + blockchainId = cryptoCurrency.network.id.value, + derivationPath = cryptoCurrency.network.derivationPath.value, + destinationAddress = confirmData.enteredDestination.orEmpty(), + tokenSymbol = null, + amount = params.nftAsset.amount.toString(), + fee = confirmData.fee?.amount?.value?.stripZeroPlainString(), + ), + ) + + val cardInfo = getCardInfoUseCase(userWallet.scanResponse).getOrNull() ?: return + + modelScope.launch { + sendFeedbackEmailUseCase(type = FeedbackEmailType.TransactionSendingProblem(cardInfo = cardInfo)) + } } private fun initialState() { @@ -229,9 +273,9 @@ internal class NFTSendConfirmModel @Inject constructor( ifLeft = { error -> Timber.e(error) _uiState.update(NFTSendConfirmSendingStateTransformer(isSending = false)) - // alertFactory.getGenericErrorState { - // onFailedTxEmailClick(error.localizedMessage.orEmpty()) - // } + alertFactory.getGenericErrorState { + onFailedTxEmailClick(error.localizedMessage.orEmpty()) + } }, ifRight = { txData -> sendTransaction(txData) @@ -252,17 +296,22 @@ internal class NFTSendConfirmModel @Inject constructor( result.fold( ifLeft = { error -> Timber.e(error.toString()) - // alertFactory.getSendTransactionErrorState( - // error = error, - // popBack = appRouter::pop, - // onFailedTxEmailClick = ::onFailedTxEmailClick, - // ) - // analyticsEventHandler.send(SendAnalyticEvents.TransactionError(cryptoCurrency.symbol)) + alertFactory.getSendTransactionErrorState( + error = error, + popBack = appRouter::pop, + onFailedTxEmailClick = ::onFailedTxEmailClick, + ) + analyticsEventHandler.send( + CommonSendAnalyticEvents.TransactionError( + categoryName = analyticsCategoryName, + token = cryptoCurrency.symbol, + ), + ) }, ifRight = { updateTransactionStatus(txData) sendBalanceUpdater.scheduleUpdates() - // sendAnalyticHelper.sendSuccessAnalytics(cryptoCurrency, uiState.value) + nftSendAnalyticHelper.nftSendSuccessAnalytics(cryptoCurrency, uiState.value) }, ) } @@ -307,6 +356,7 @@ internal class NFTSendConfirmModel @Inject constructor( feeUM = uiState.value.feeUM, analyticsEventHandler = analyticsEventHandler, cryptoCurrency = cryptoCurrencyStatus.currency, + analyticsCategoryName = analyticsCategoryName, ).transform(uiState.value.confirmUM), ) } @@ -331,7 +381,8 @@ internal class NFTSendConfirmModel @Inject constructor( backIconRes = R.drawable.ic_close_24, backIconClick = { analyticsEventHandler.send( - SendAnalyticEvents.CloseButtonClicked( + CommonSendAnalyticEvents.CloseButtonClicked( + categoryName = analyticsCategoryName, source = SendScreenSource.Confirm, isFromSummary = true, isValid = confirmUM.isPrimaryButtonEnabled, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/transformers/NFTSendConfirmationNotificationsTransformer.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/transformers/NFTSendConfirmationNotificationsTransformer.kt index af93239501..f5b2ba2744 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/transformers/NFTSendConfirmationNotificationsTransformer.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/transformers/NFTSendConfirmationNotificationsTransformer.kt @@ -5,8 +5,8 @@ import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.ui.utils.parseToBigDecimal import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents 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.subcomponents.fee.model.checkIfFeeTooHigh import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeSelectorUM import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeType @@ -18,6 +18,7 @@ internal class NFTSendConfirmationNotificationsTransformer( private val feeUM: FeeUM, private val analyticsEventHandler: AnalyticsEventHandler, private val cryptoCurrency: CryptoCurrency, + private val analyticsCategoryName: String, ) : Transformer { override fun transform(prevState: ConfirmUM): ConfirmUM { val state = prevState as? ConfirmUM.Content ?: return prevState @@ -39,7 +40,10 @@ internal class NFTSendConfirmationNotificationsTransformer( if (feeSelectorUM.selectedType == FeeType.Custom && minimumValue > customValue) { add(NotificationUM.Warning.FeeTooLow) analyticsEventHandler.send( - SendAnalyticEvents.NoticeTransactionDelays(cryptoCurrency.symbol), + CommonSendAnalyticEvents.NoticeTransactionDelays( + categoryName = analyticsCategoryName, + token = cryptoCurrency.symbol, + ), ) } } diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt index 71fb3be509..8146fab729 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt @@ -13,6 +13,11 @@ import com.tangem.datasource.local.nft.converter.NFTSdkAssetConverter import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.common.util.cardTypesResolver +import com.tangem.domain.feedback.GetCardInfoUseCase +import com.tangem.domain.feedback.SaveBlockchainErrorUseCase +import com.tangem.domain.feedback.SendFeedbackEmailUseCase +import com.tangem.domain.feedback.models.BlockchainErrorInfo +import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase @@ -25,6 +30,7 @@ import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.send.v2.api.NFTSendComponent 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.common.ui.state.NavigationUM import com.tangem.features.send.v2.sendnft.confirm.NFTSendConfirmComponent @@ -58,6 +64,10 @@ internal class NFTSendModel @Inject constructor( private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val createNFTTransferTransactionUseCase: CreateNFTTransferTransactionUseCase, private val getFeeUseCase: GetFeeUseCase, + private val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase, + private val getCardInfoUseCase: GetCardInfoUseCase, + private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, + private val alertFactory: SendConfirmAlertFactory, ) : Model(), SendNFTComponentCallback { val params: NFTSendComponent.Params = paramsContainer.require() @@ -145,13 +155,33 @@ internal class NFTSendModel @Inject constructor( ) }, ifLeft = { - // sendConfirmAlertFactory.getGenericErrorState(::onFailedTxEmailClick) + alertFactory.getGenericErrorState(::onFailedTxEmailClick) return@launch }, ) } } + private fun onFailedTxEmailClick(errorMessage: String? = null) { + saveBlockchainErrorUseCase( + error = BlockchainErrorInfo( + errorMessage = errorMessage.orEmpty(), + blockchainId = cryptoCurrency.network.id.value, + derivationPath = cryptoCurrency.network.derivationPath.value, + destinationAddress = "", + tokenSymbol = null, + amount = "", + fee = "", + ), + ) + + val cardInfo = getCardInfoUseCase(userWallet.scanResponse).getOrNull() ?: return + + modelScope.launch { + sendFeedbackEmailUseCase(type = FeedbackEmailType.TransactionSendingProblem(cardInfo = cardInfo)) + } + } + private fun getCurrenciesStatusUpdates(isSingleWalletWithToken: Boolean) { getCurrencyStatusUpdatesUseCase( userWalletId = userWalletId, @@ -171,9 +201,9 @@ internal class NFTSendModel @Inject constructor( } }, ifLeft = { - // sendConfirmAlertFactory.getGenericErrorState { - // onFailedTxEmailClick(it.toString()) - // } + alertFactory.getGenericErrorState { + onFailedTxEmailClick(it.toString()) + } }, ) }.launchIn(modelScope)