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)