diff --git a/app/src/main/java/com/tangem/tap/common/url/CustomTabsUrlOpener.kt b/app/src/main/java/com/tangem/tap/common/url/CustomTabsUrlOpener.kt
index 965d6caacd..de65ad7aa7 100644
--- a/app/src/main/java/com/tangem/tap/common/url/CustomTabsUrlOpener.kt
+++ b/app/src/main/java/com/tangem/tap/common/url/CustomTabsUrlOpener.kt
@@ -3,12 +3,12 @@ package com.tangem.tap.common.url
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
-import android.net.Uri
import androidx.browser.customtabs.CustomTabColorSchemeParams
import androidx.browser.customtabs.CustomTabsClient
import androidx.browser.customtabs.CustomTabsIntent
import androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_DARK
import androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_LIGHT
+import androidx.core.net.toUri
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder
import com.tangem.tap.common.extensions.getColorCompat
@@ -25,30 +25,37 @@ internal class CustomTabsUrlOpener : UrlOpener {
}
}
+ override fun openUrlExternalBrowser(url: String) {
+ foregroundActivityObserver.withForegroundActivity { context ->
+ if (url.isEmpty()) return@withForegroundActivity
+ val browserIntent = Intent(Intent.ACTION_VIEW, url.toUri())
+ context.startActivity(browserIntent)
+ }
+ }
+
private fun openUrl(url: String, context: Context) {
if (url.isEmpty()) return
- val customTabsIntent = CustomTabsIntent.Builder()
- .setDefaultColorSchemeParams(
- CustomTabColorSchemeParams.Builder()
- .setNavigationBarColor(context.getColorCompat(R.color.toolbarColor))
- .build(),
- )
- .setColorScheme(
- if (MutableAppThemeModeHolder.isDarkThemeActive) COLOR_SCHEME_DARK else COLOR_SCHEME_LIGHT,
- )
- .build()
-
- customTabsIntent.intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
-
- val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
+ val browserIntent = Intent(Intent.ACTION_VIEW, url.toUri())
runCatching {
if (checkCustomTabsAvailability(context, browserIntent)) {
context.startActivity(browserIntent)
} else {
- customTabsIntent.launchUrl(context, Uri.parse(url))
+ val customTabsIntent = CustomTabsIntent.Builder()
+ .setDefaultColorSchemeParams(
+ CustomTabColorSchemeParams.Builder()
+ .setNavigationBarColor(context.getColorCompat(R.color.toolbarColor))
+ .build(),
+ )
+ .setColorScheme(
+ if (MutableAppThemeModeHolder.isDarkThemeActive) COLOR_SCHEME_DARK else COLOR_SCHEME_LIGHT,
+ )
+ .build()
+
+ customTabsIntent.intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
+ customTabsIntent.launchUrl(context, url.toUri())
}
}.onFailure {
- Timber.e(it.message)
+ Timber.e(it)
}
}
diff --git a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json
index d33f1e1360..6ecb2f5ac6 100644
--- a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json
+++ b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json
@@ -21,7 +21,7 @@
},
{
"name": "WALLET_CONNECT_REDESIGN_ENABLED",
- "version": "undefined"
+ "version": "5.27.0"
},
{
"name": "PUSH_NOTIFICATIONS_ENABLED",
diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/blockaid/models/response/AssetDiff.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/blockaid/models/response/AssetDiff.kt
index 51e5374ae8..be70cd4a52 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/api/common/blockaid/models/response/AssetDiff.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/blockaid/models/response/AssetDiff.kt
@@ -15,8 +15,8 @@ data class AssetDiff(
data class Asset(
@Json(name = "chain_id") val chainId: Int? = null,
@Json(name = "logo_url") val logoUrl: String? = null,
- @Json(name = "symbol") val symbol: String,
- @Json(name = "decimals") val decimals: Int,
+ @Json(name = "symbol") val symbol: String? = null,
+ @Json(name = "decimals") val decimals: Int? = null,
)
@JsonClass(generateAdapter = true)
diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/blockaid/models/response/Exposure.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/blockaid/models/response/Exposure.kt
index 0ed36e6a25..e776056d4c 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/api/common/blockaid/models/response/Exposure.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/blockaid/models/response/Exposure.kt
@@ -18,6 +18,8 @@ data class SpenderDetails(
@JsonClass(generateAdapter = true)
data class ExposureDetail(
- @Json(name = "value") val value: String,
- @Json(name = "raw_value") val rawValue: String,
+ @Json(name = "value") val value: String? = null,
+ @Json(name = "raw_value") val rawValue: String? = null,
+ @Json(name = "token_id") val tokenId: String? = null,
+ @Json(name = "logo_url") val logoUrl: String? = null,
)
\ No newline at end of file
diff --git a/core/navigation/src/main/java/com/tangem/core/navigation/url/DummyUrlOpener.kt b/core/navigation/src/main/java/com/tangem/core/navigation/url/DummyUrlOpener.kt
index cff4946b40..d47667b064 100644
--- a/core/navigation/src/main/java/com/tangem/core/navigation/url/DummyUrlOpener.kt
+++ b/core/navigation/src/main/java/com/tangem/core/navigation/url/DummyUrlOpener.kt
@@ -5,4 +5,8 @@ class DummyUrlOpener : UrlOpener {
override fun openUrl(url: String) {
/* no-op */
}
+
+ override fun openUrlExternalBrowser(url: String) {
+ /* no-op */
+ }
}
\ No newline at end of file
diff --git a/core/navigation/src/main/java/com/tangem/core/navigation/url/UrlOpener.kt b/core/navigation/src/main/java/com/tangem/core/navigation/url/UrlOpener.kt
index d78ba1b1eb..df94cdfacf 100644
--- a/core/navigation/src/main/java/com/tangem/core/navigation/url/UrlOpener.kt
+++ b/core/navigation/src/main/java/com/tangem/core/navigation/url/UrlOpener.kt
@@ -3,4 +3,6 @@ package com.tangem.core.navigation.url
interface UrlOpener {
fun openUrl(url: String)
+
+ fun openUrlExternalBrowser(url: String)
}
\ No newline at end of file
diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml
index 075f05f465..b28e3174c2 100644
--- a/core/res/src/main/res/values-fr/strings.xml
+++ b/core/res/src/main/res/values-fr/strings.xml
@@ -66,6 +66,10 @@
- %d carte
- %d cartes
+
+ - %s token
+ - %s tokens
+
Désactivez cette option si vous ne voulez pas que cette carte soit utilisée pour réinitialiser les codes d\'accès sur d\'autres cartes de ce portefeuille. Veuillez noter que cela vous empêchera également de réinitialiser le code d\'accès sur cette carte.
Vous permet d\'utiliser cette carte pour réinitialiser le code d\'accès sur d\'autres cartes de ce portefeuille
Récupération du code d\'accès
@@ -111,6 +115,7 @@
Annuler
Changez
Choisissez une action
+ Choisissez le réseau
Choisir le jeton
Réclamer
Réclamez des récompenses
@@ -152,6 +157,7 @@
Synchroniser les adresses
Aller au fournisseur
Aller au jeton
+ Compris
Cacher
heure
Importez
@@ -196,6 +202,7 @@
Le serveur n\'est pas disponible, veuillez réessayer plus tard
Partager
Partager le lien
+ Afficher moins
Afficher plus
Signez
Signez et envoyez
@@ -205,6 +212,7 @@
Soumettre
Avec succès
Support
+ Réseaux pris en charge
Échanger
termes et conditions
Conditions d\'utilisation
@@ -265,6 +273,7 @@
%s hashes
ID de l\'appareil
Contactez l\'équipe de support
+ Ouvrir le chat d\'assistance
Lier plus de cartes
Monnaie de l\'application
Retourner pour masquer les soldes
@@ -281,6 +290,7 @@
Ne peut pas être échangé contre %s
Fourni par
Statut
+ Choisir un fournisseur
Tangem propose des échanges de jetons via des fournisseurs tiers selon les conditions de chaque fournisseur
Fournisseur
Une erreur s\'est produite. Code : %s
@@ -340,6 +350,9 @@
Masquer cette transaction
Une fois masqué, le statut de la transaction ne peut plus être consulté. Vous pouvez simplement faire glisser votre doigt pour le fermer.
Masquer le statut de la transaction ?
+ Ce jeton n\'est pas pris en charge. Veuillez choisir un autre jeton à échanger.
+ %s n\'est pas pris en charge
+ Échanger avec
Aucun jeton trouvé. Veuillez essayer une autre demande
ID : %s
ID de transaction copié
@@ -367,6 +380,8 @@
Pour continuer, accordez aux smart contracts de %1s l\'autorisation d\'utiliser votre %2s
Donner l\'autorisation
Illimité
+ Ajouter un Portefeuille existant
+ Créer un nouveau Portefeuille
Commandez
Scannez
à %s
@@ -423,6 +438,7 @@
Cet actif n\'est pas pris en charge dans le portefeuille
Cet actif n\'est pas disponible pour ce portefeuille
Ajoutez un jeton
+ APY %s
Réseaux disponibles
Mon portfolio
Marché
@@ -709,6 +725,7 @@
Paramètres
Activer les notifications
Recevez des alertes pour les transactions entrantes sur les réseaux pris en charge.
+ Notifications de transaction
Sélectionnez dans la galerie
Paramètres
Vous n\'avez pas donné accès à votre caméra
@@ -818,6 +835,9 @@
Mémo : %s
Mémo invalide
Couverture des frais de réseau
+ Nonce
+ Numéro unique pour chaque transaction. Utilisez-le pour renvoyer ou annuler une transaction en attente.
+ Entrez le nonce…
Fonds insuffisants pour le transfert, car le total des frais et du montant du transfert dépasse le solde existant
Le total dépasse le solde
Un solde d\'au moins %s est requis pour conserver votre compte sur la blockchain afin d\'éviter les risques de sécurité. Ce montant restera sur votre solde et ne pourra pas être retiré.
@@ -847,6 +867,7 @@
Adresse non valide
Assurez-vous que l\'adresse du portefeuille de réception est sur le réseau %s pour éviter de perdre vos jetons
envoyer à %s
+ Assurez-vous de %s une adresse réseau, car des erreurs peuvent entraîner des transferts perdus
Envoyer à
Un Memo/Destination Tag est un identifiant unique permettant de différencier les transactions envoyées au même destinataire sur le même réseau. Attention : L\'omission d\'un mémo peut entraîner des fonds mal placés
Le Memo / Destination Tag est un code qui distingue les transactions envoyées à un destinataire partagé sur un réseau crypto.
@@ -873,7 +894,11 @@
Les frais de commissions dépassent le solde
Le total dépasse le solde
Échanger et envoyer
+ Envoyez n\'importe quel jeton et nous le convertirons en cours de route. Votre destinataire reçoit exactement ce dont il a besoin, en toute simplicité.
+ Le destinataire recevra
+ Un destinataire sera envoyé
Montant à recevoir
+ Envoyer avec swap
Transaction envoyée
Scannez la carte/ bague que vous souhaitez configurer.
Oublier le portefeuille
@@ -1014,6 +1039,7 @@
Compatible avec Web 3.0
Une transaction entrante d\'au moins de %1$s est requise pour continuer
Fonds insuffisants
+ Taux fixe
Le réseau facturera des frais d\'approbation de jeton pour vérifier que vous autorisez l\'utilisation de votre jeton pour l\'échange.
Échangez plus de jetons à de meilleurs taux directement dans votre portefeuille.
Nouveau fournisseur d\'échange disponible !
@@ -1091,6 +1117,8 @@
Notifications de transaction
Minimum %s
Le montant minimum pour effectuer cette transaction est %1$s.
+ Les frais de réseau Tron pour les jetons populaires peuvent être plus élevés. Le staking de TRX peut contribuer à réduire les coûts de transaction.
+ Économisez sur les frais de réseau Tron
Réessayez
Vous avez scanné la même carte. Pour créer un portefeuille jumeau, vous devez scanner la carte portant le numéro %d
Vous avez scanné une mauvaise carte jumelle. S\'il vous plaît, essayez-en un autre
@@ -1103,6 +1131,8 @@
Tangem Twin
Cette action est irréversible. Vous n\'aurez plus accès à l\'ancien portefeuille.
Appuyez sur la carte jumelle avec le numéro %s et ne la retirez pas jusqu\'à la fin de l\'opération
+ Veuillez réessayer ultérieurement. Si le problème persiste, veuillez contacter le support.
+ Une erreur s\'est produite !
Nous avons rencontré une erreur. Code d\'erreur : %s. Veuillez contacter notre équipe de support.
Utilisez %s ou scannez une carte/bague pour avoir accès à votre portefeuille
Échec de la connexion : Cette dApp utilise Wallet Connect version1.0, qui n\'est pas prise en charge. Veuillez vous assurer que la dApp prend en charge Wallet Connect version2.0 pour réussir la connexion.
@@ -1253,6 +1283,7 @@
Votre avis nous motive à améliorer encore le Portefeuille Tangem
Vous appréciez Tangem ?
Vous devez associer votre jeton avant de recevoir des jetons
+ Vous devez ouvrir la ligne de confiance pour votre jeton avant de le recevoir
Frais de location de réseau requis
Action requise
Avez-vous contacté l\'assistance via l\'application ou par e-mail dans les 7 jours suivant la création d\'un portefeuille ? Si vous l\'avez fait ou si vous n\'êtes pas sûr, suivez et complétez les instructions.
@@ -1273,17 +1304,38 @@
À des fins de test uniquement
Le solde peut être obsolète. Rafraîchissez la page.
Pas assez de %1$s. Rechargez votre compte %2$s pour associer ce jeton.
+ Activer Trustline
+ Une Trustline doit être activée pour recevoir ce jeton. Le réseau requiert une réserve de %1$s %2$s
+ Trustline requise
Domaine malveillant
+ Signer quand même
Si le problème persiste, n’hésitez pas à contacter notre support.
Le portefeuille Tangem ne prend actuellement pas en charge %ss
dApp non prise en charge
+ Code d\'erreur : 8 005. Si le problème persiste, n\'hésitez pas à contacter notre support.
+ Nous avons rencontré une erreur inconnue
+ Autoriser à dépenser
+ Adresse
+ Chargement
+ Illimité
Connexions
+ Contenu
+ Copier les données
Déconnecter tout
Texte sur la déconnexion de toutes les dApps
Déconnecter toutes les dApps
+ Modifications estimées du portefeuille
+ La transaction n\'a pas pu être simulée. Veuillez procéder avec prudence.
+ Transaction malveillante
Nouvelle connexion
Connectez votre portefeuille à différentes dApps
Aucune séance
+ Demande de
+ Type de signature
+ À
+ Demande de transaction
+ Demande de transaction
+ Montant illimité
Ignorer
Vous avez une sauvegarde interrompue. Voulez-vous la reprendre ?
Oui, reprendre
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index a8961f599c..704c48f319 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -12,6 +12,7 @@
Set a %s-digit Access Code to unlock your wallet.
Create Access Code
Access code
+ Account name
Can’t find your token? Go to the Market section on the main page and add it to your portfolio for purchase
Can’t find your token? Go to the Market section on the main page and add it to your portfolio for selling.
Sell
@@ -1500,6 +1501,7 @@
New connection
Connect your wallet to a different dApps
No sessions
+ No wallet changes detected
This domain is flagged as unsafe by multiple security providers. Leave immediately to protect your assets
Known security risk
Request from
@@ -1511,6 +1513,7 @@
Ensure that each pairing attempt uses a fresh and unique URI
URI already used
Wallet connect
+ Suspicious transaction
Discard
You have an interrupted backup. Do you want to resume?
Yes, resume
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt
index 1e2279b8c2..7b1baa0109 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt
@@ -214,12 +214,15 @@ internal fun TextsBlock(
SpacerH(height = TangemTheme.dimens.spacing2)
}
- Text(
- text = subtitle.resolveReference(),
- color = subtitleColor,
- style = TangemTheme.typography.caption2,
- modifier = Modifier.testTag(NotificationTestTags.TEXT),
- )
+ val subtitleText = subtitle.resolveReference()
+ if (subtitleText.isNotEmpty()) {
+ Text(
+ text = subtitleText,
+ color = subtitleColor,
+ style = TangemTheme.typography.caption2,
+ modifier = Modifier.testTag(NotificationTestTags.TEXT),
+ )
+ }
}
}
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/tooltip/TangemTooltip.kt b/core/ui/src/main/java/com/tangem/core/ui/components/tooltip/TangemTooltip.kt
index b436ca3287..395b09aed0 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/tooltip/TangemTooltip.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/tooltip/TangemTooltip.kt
@@ -22,9 +22,15 @@ import com.tangem.core.ui.res.TangemThemePreview
import kotlinx.coroutines.launch
@Composable
-fun TangemTooltip(text: String, content: @Composable (Modifier) -> Unit, modifier: Modifier = Modifier) {
+fun TangemTooltip(
+ text: String,
+ content: @Composable (Modifier) -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+) {
InternalTangemTooltip(
modifier = modifier,
+ enabled = enabled,
tooltipContent = {
Text(
modifier = Modifier.background(TangemTheme.colors.icon.secondary),
@@ -38,9 +44,15 @@ fun TangemTooltip(text: String, content: @Composable (Modifier) -> Unit, modifie
}
@Composable
-fun TangemTooltip(text: AnnotatedString, content: @Composable (Modifier) -> Unit, modifier: Modifier = Modifier) {
+fun TangemTooltip(
+ text: AnnotatedString,
+ content: @Composable (Modifier) -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+) {
InternalTangemTooltip(
modifier = modifier,
+ enabled = enabled,
tooltipContent = {
Text(
modifier = Modifier.background(TangemTheme.colors.icon.secondary),
@@ -59,6 +71,7 @@ private fun InternalTangemTooltip(
tooltipContent: @Composable () -> Unit,
content: @Composable (Modifier) -> Unit,
modifier: Modifier = Modifier,
+ enabled: Boolean = true,
) {
val tooltipState = rememberTooltipState(isPersistent = true)
val coroutineScope = rememberCoroutineScope()
@@ -78,11 +91,14 @@ private fun InternalTangemTooltip(
)
},
content = {
- content(
+ val contentModifier = if (enabled) {
Modifier.clickableSingle(
onClick = { coroutineScope.launch { tooltipState.show() } },
- ),
- )
+ )
+ } else {
+ Modifier
+ }
+ content(contentModifier)
},
)
}
diff --git a/data/blockaid/src/main/kotlin/com/tangem/data/blockaid/BlockAidMapper.kt b/data/blockaid/src/main/kotlin/com/tangem/data/blockaid/BlockAidMapper.kt
index e245687538..128d1cfd56 100644
--- a/data/blockaid/src/main/kotlin/com/tangem/data/blockaid/BlockAidMapper.kt
+++ b/data/blockaid/src/main/kotlin/com/tangem/data/blockaid/BlockAidMapper.kt
@@ -16,6 +16,7 @@ import org.json.JSONArray
private const val SUCCESS_STATUS = "Success"
private const val DOMAIN_CHECKED_STATUS = "hit"
private const val VALIDATION_SAFE_STATUS = "Benign"
+private const val VALIDATION_WARNING_STATUS = "Warning"
internal object BlockAidMapper {
@@ -32,6 +33,7 @@ internal object BlockAidMapper {
validation = when {
from.validation.status != SUCCESS_STATUS -> ValidationResult.FAILED_TO_VALIDATE
from.validation.resultType == VALIDATION_SAFE_STATUS -> ValidationResult.SAFE
+ from.validation.resultType == VALIDATION_WARNING_STATUS -> ValidationResult.WARNING
else -> ValidationResult.UNSAFE
},
simulation = if (from.simulation.status != SUCCESS_STATUS) {
@@ -83,7 +85,7 @@ internal object BlockAidMapper {
from.exposures,
)
!from.traces.isNullOrEmpty() -> mapNftSendReceiveTransaction(from.traces)
- else -> SimulationResult.FailedToSimulate
+ else -> SimulationResult.Success(data = SimulationData.NoWalletChangesDetected)
}
}
@@ -92,15 +94,15 @@ internal object BlockAidMapper {
val tokenInfo = TokenInfo(
chainId = exposure.asset.chainId,
logoUrl = exposure.asset.logoUrl,
- symbol = exposure.asset.symbol,
- decimals = exposure.asset.decimals,
+ symbol = exposure.asset.symbol ?: "",
+ decimals = exposure.asset.decimals ?: 0,
)
exposure.spenders.flatMap { (_, spender) ->
val isUnlimited = spender.isApprovedForAll == true
val approval = spender.approval?.hexToBigDecimal()
- spender.exposure.mapNotNull { detail ->
+ spender.exposure.map { detail ->
ApprovedAmount(
- approvedAmount = detail.value.toBigDecimalOrNull() ?: approval ?: return@mapNotNull null,
+ approvedAmount = detail.value?.toBigDecimalOrNull() ?: approval ?: 1.toBigDecimal(),
isUnlimited = isUnlimited,
tokenInfo = tokenInfo,
)
@@ -110,7 +112,7 @@ internal object BlockAidMapper {
return if (!amounts.isNullOrEmpty()) {
SimulationResult.Success(SimulationData.Approve(amounts))
} else {
- SimulationResult.FailedToSimulate
+ SimulationResult.Success(SimulationData.NoWalletChangesDetected)
}
}
@@ -122,8 +124,8 @@ internal object BlockAidMapper {
val token = TokenInfo(
chainId = diff.asset.chainId,
logoUrl = diff.asset.logoUrl,
- symbol = diff.asset.symbol,
- decimals = diff.asset.decimals,
+ symbol = diff.asset.symbol ?: "",
+ decimals = diff.asset.decimals ?: 0,
)
diff.outTransfer.orEmpty().forEach { transfer ->
transfer.value?.toBigDecimalOrNull()?.let { amount ->
@@ -140,7 +142,7 @@ internal object BlockAidMapper {
return if (sendInfo.isNotEmpty() || receiveInfo.isNotEmpty()) {
SimulationResult.Success(SimulationData.SendAndReceive(send = sendInfo, receive = receiveInfo))
} else {
- SimulationResult.FailedToSimulate
+ SimulationResult.Success(SimulationData.NoWalletChangesDetected)
}
}
@@ -154,7 +156,7 @@ internal object BlockAidMapper {
return if (!sendInfo.isNullOrEmpty()) {
SimulationResult.Success(SimulationData.SendAndReceive(send = sendInfo, receive = listOf()))
} else {
- SimulationResult.FailedToSimulate
+ SimulationResult.Success(SimulationData.NoWalletChangesDetected)
}
}
}
\ No newline at end of file
diff --git a/data/blockaid/src/test/kotlin/com/tangem/data/blockaid/BlockAidMapperTest.kt b/data/blockaid/src/test/kotlin/com/tangem/data/blockaid/BlockAidMapperTest.kt
index 1980d63605..00dd54e198 100644
--- a/data/blockaid/src/test/kotlin/com/tangem/data/blockaid/BlockAidMapperTest.kt
+++ b/data/blockaid/src/test/kotlin/com/tangem/data/blockaid/BlockAidMapperTest.kt
@@ -114,7 +114,7 @@ class BlockAidMapperTest {
val result = mapper.mapToDomain(response)
Truth.assertThat(result.validation).isEqualTo(ValidationResult.FAILED_TO_VALIDATE)
- Truth.assertThat(result.simulation is SimulationResult.FailedToSimulate).isTrue()
+ Truth.assertThat(result.simulation is SimulationResult.Success).isTrue()
}
@Test
@@ -160,6 +160,6 @@ class BlockAidMapperTest {
)
val result = mapper.mapToDomain(txResponse)
- Truth.assertThat(result.simulation is SimulationResult.FailedToSimulate).isTrue()
+ Truth.assertThat(result.simulation is SimulationResult.Success).isTrue()
}
}
\ No newline at end of file
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt
index 40593c27e5..0ee7dab28e 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt
@@ -225,8 +225,12 @@ internal object WalletConnectDataModule {
@Provides
@Singleton
- fun wcRequestUseCaseFactory(diHelperBox: DiHelperBox): WcRequestUseCaseFactory {
- return DefaultWcRequestUseCaseFactory(diHelperBox.handlers)
+ fun wcRequestUseCaseFactory(
+ diHelperBox: DiHelperBox,
+ namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>,
+ analytics: AnalyticsEventHandler,
+ ): WcRequestUseCaseFactory {
+ return DefaultWcRequestUseCaseFactory(diHelperBox.handlers, namespaceConverters, analytics)
}
@Provides
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt
index 7b7823fd7f..0f9e21543f 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt
@@ -7,7 +7,6 @@ import arrow.core.right
import com.squareup.moshi.Moshi
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
-import com.tangem.blockchainsdk.utils.toBlockchain
import com.tangem.data.walletconnect.model.CAIP2
import com.tangem.data.walletconnect.model.NamespaceKey
import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter
@@ -15,7 +14,6 @@ import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter.Compani
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
import com.tangem.data.walletconnect.utils.WcNetworksConverter
-import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.walletconnect.model.*
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
@@ -156,16 +154,6 @@ internal class WcEthNetwork(
val ethChainId = chainId.reference.toIntOrNull() ?: return null
return Blockchain.fromChainId(ethChainId)
}
-
- override fun toCAIP2(network: Network): CAIP2? {
- val blockchain = network.toBlockchain()
- if (!blockchain.isEvm()) return null
- val chainId = blockchain.getChainId() ?: return null
- return CAIP2(
- namespace = namespaceKey.key,
- reference = chainId.toString(),
- )
- }
}
internal class Factories @Inject constructor(
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSendTransactionUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSendTransactionUseCase.kt
index 0621f51855..5358c3a317 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSendTransactionUseCase.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSendTransactionUseCase.kt
@@ -41,6 +41,9 @@ internal class WcEthSendTransactionUseCase @AssistedInject constructor(
WcMutableFee {
private var approvalAmount: WcApprovedAmount? = null
+ // in case of change TransactionExtras
+ // change approvalAmount for example
+ private var isIgnoreDAppFee: Boolean = false
private var dAppFee: Fee? = null
override val securityStatus: LceFlow =
@@ -102,7 +105,7 @@ internal class WcEthSendTransactionUseCase @AssistedInject constructor(
},
)
approvalAmount = action.amount
- dAppFee = null
+ isIgnoreDAppFee = true
uncompiled.copy(extras = extras.copy(callData = callData))
}
is WcEthTxAction.UpdateFee -> uncompiled.copy(fee = action.fee)
@@ -111,8 +114,11 @@ internal class WcEthSendTransactionUseCase @AssistedInject constructor(
emit(newState)
}
- override fun dAppFee(): Fee? {
- return dAppFee
+ override suspend fun dAppFee(): Fee? {
+ if (isIgnoreDAppFee) return null
+ if (dAppFee != null) return dAppFee
+ return ethTxHelper.getDAppFee(method.transaction, wallet, network)
+ .also { dAppFee = it }
}
override fun updateFee(fee: Fee) {
@@ -120,9 +126,8 @@ internal class WcEthSendTransactionUseCase @AssistedInject constructor(
}
override fun invoke(): Flow> = flow {
- dAppFee = ethTxHelper.getDAppFee(method.transaction, wallet, network)
val transactionData = ethTxHelper.createTransactionData(
- dAppFee = dAppFee,
+ dAppFee = dAppFee(),
network = context.network,
txParams = method.transaction,
) ?: return@flow
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTransactionUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTransactionUseCase.kt
index eda9598750..b6795bf29b 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTransactionUseCase.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTransactionUseCase.kt
@@ -41,6 +41,9 @@ internal class WcEthSignTransactionUseCase @AssistedInject constructor(
WcMutableFee {
private var approvalAmount: WcApprovedAmount? = null
+ // in case of change TransactionExtras
+ // change approvalAmount for example
+ private var isIgnoreDAppFee: Boolean = false
private var dAppFee: Fee? = null
override val securityStatus = blockAidDelegate.getSecurityStatus(
@@ -101,7 +104,7 @@ internal class WcEthSignTransactionUseCase @AssistedInject constructor(
},
)
approvalAmount = action.amount
- dAppFee = null
+ isIgnoreDAppFee = true
uncompiled.copy(extras = extras.copy(callData = callData))
}
is WcEthTxAction.UpdateFee -> uncompiled.copy(fee = action.fee)
@@ -115,17 +118,19 @@ internal class WcEthSignTransactionUseCase @AssistedInject constructor(
}
override fun invoke(): Flow> = flow {
- dAppFee = ethTxHelper.getDAppFee(method.transaction, wallet, network)
val transactionData = ethTxHelper.createTransactionData(
- dAppFee = dAppFee,
+ dAppFee = dAppFee(),
network = context.network,
txParams = method.transaction,
) ?: return@flow
emitAll(delegate.invoke(transactionData))
}
- override fun dAppFee(): Fee? {
- return dAppFee
+ override suspend fun dAppFee(): Fee? {
+ if (isIgnoreDAppFee) return null
+ if (dAppFee != null) return dAppFee
+ return ethTxHelper.getDAppFee(method.transaction, wallet, network)
+ .also { dAppFee = it }
}
override fun getAmount(): WcApprovedAmount? {
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthTxHelper.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthTxHelper.kt
index ebf796f991..057afaa2e9 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthTxHelper.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthTxHelper.kt
@@ -76,7 +76,7 @@ internal class WcEthTxHelper @Inject constructor(
?: return null
val approves = (simulation.data as? SimulationData.Approve)?.approvedAmounts
?: return null
- if (approves.size != 1) return null
+ if (approves.isEmpty()) return null
val amount = approves.first()
return amount
}
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt
index 8fa3aa5469..0b47155291 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt
@@ -8,7 +8,6 @@ import com.squareup.moshi.Moshi
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.extensions.decodeBase58
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
-import com.tangem.blockchainsdk.utils.toBlockchain
import com.tangem.common.extensions.toHexString
import com.tangem.data.walletconnect.model.CAIP2
import com.tangem.data.walletconnect.model.NamespaceKey
@@ -17,7 +16,6 @@ import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter.Compani
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
import com.tangem.data.walletconnect.utils.WcNetworksConverter
-import com.tangem.domain.models.network.Network
import com.tangem.domain.walletconnect.model.HandleMethodError
import com.tangem.domain.walletconnect.model.WcSolanaMethod
import com.tangem.domain.walletconnect.model.WcSolanaMethodName
@@ -88,27 +86,14 @@ internal class WcSolanaNetwork(
override val namespaceKey: NamespaceKey = NamespaceKey("solana")
override fun toBlockchain(chainId: CAIP2): Blockchain? {
+ val isMainNet = MAINNET_CHAIN_ID.any { it.lowercase() == chainId.reference.lowercase() }
if (chainId.namespace != namespaceKey.key) return null
- return when (chainId.reference) {
- MAINNET_CHAIN_ID -> Blockchain.Solana
- TESTNET_CHAIN_ID -> Blockchain.SolanaTestnet
+ return when {
+ isMainNet -> Blockchain.Solana
+ chainId.reference.lowercase() == TESTNET_CHAIN_ID -> Blockchain.SolanaTestnet
else -> null
}
}
-
- override fun toCAIP2(network: Network): CAIP2? {
- val blockchain = network.toBlockchain()
- val chainId = when (blockchain) {
- Blockchain.Solana -> MAINNET_CHAIN_ID
- Blockchain.SolanaTestnet -> TESTNET_CHAIN_ID
- else -> null
- }
- chainId ?: return null
- return CAIP2(
- namespace = namespaceKey.key,
- reference = chainId,
- )
- }
}
private fun WcSolanaMethodName.toMethod(request: WcSdkSessionRequest): Either {
@@ -140,7 +125,7 @@ internal class WcSolanaNetwork(
)
companion object {
- private const val MAINNET_CHAIN_ID = "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
+ private val MAINNET_CHAIN_ID = listOf("5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")
private const val TESTNET_CHAIN_ID = "4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z"
}
}
\ No newline at end of file
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt
index 7ecdf54de9..d0f06c74b2 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt
@@ -110,8 +110,10 @@ internal class AssociateNetworksDelegate(
.distinctBy { it.rawId }
}
- private fun Map.setOfChainId(): Set =
- this.values.flatMap { proposal -> proposal.chains ?: listOf() }.toSet()
-
private fun missingNetworkName(chainId: String): String = chainId.replaceFirstChar(Char::titlecase)
+
+ companion object {
+ internal fun Map.setOfChainId(): Set =
+ this.values.flatMap { proposal -> proposal.chains ?: listOf() }.toSet()
+ }
}
\ No newline at end of file
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/CaipNamespaceDelegate.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/CaipNamespaceDelegate.kt
index 82c921611a..4b5d2c336a 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/CaipNamespaceDelegate.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/CaipNamespaceDelegate.kt
@@ -2,6 +2,8 @@ package com.tangem.data.walletconnect.pair
import com.reown.walletkit.client.Wallet
import com.tangem.data.walletconnect.model.CAIP10
+import com.tangem.data.walletconnect.model.CAIP2
+import com.tangem.data.walletconnect.pair.AssociateNetworksDelegate.Companion.setOfChainId
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
import com.tangem.data.walletconnect.utils.WcNetworksConverter
import com.tangem.domain.models.network.Network
@@ -22,6 +24,26 @@ internal class CaipNamespaceDelegate(
val userWallet = sessionForApprove.wallet
val result = mutableMapOf()
+ val requiredNamespaces = sessionProposal.requiredNamespaces.setOfChainId()
+ val optionalNamespaces = sessionProposal.optionalNamespaces.setOfChainId()
+ val allWcNetworks = (requiredNamespaces + optionalNamespaces)
+ .mapNotNull { chainId ->
+ val network = namespaceConverters
+ .firstNotNullOfOrNull { it.toNetwork(chainId, userWallet) }
+ ?: return@mapNotNull null
+ val caip2 = CAIP2.fromRaw(chainId) ?: return@mapNotNull null
+ network to caip2
+ }
+
+ suspend fun createCAIP10(userWalletId: UserWalletId, network: Network): CAIP10? {
+ val address = walletManagersFacade.getDefaultAddress(userWalletId, network)
+ val chainId = allWcNetworks
+ .find { (wcNetwork, _) -> network.rawId == wcNetwork.rawId }
+ ?.second
+ if (chainId == null || address == null) return null
+ return CAIP10(chainId = chainId, accountAddress = address)
+ }
+
wcNetworksConverter.convertNetworksForApprove(sessionForApprove)
.mapNotNull { createCAIP10(userWallet.walletId, it) }
.forEach { account ->
@@ -52,13 +74,6 @@ internal class CaipNamespaceDelegate(
}
}
- private suspend fun createCAIP10(userWalletId: UserWalletId, network: Network): CAIP10? {
- val address = walletManagersFacade.getDefaultAddress(userWalletId, network)
- val chainId = namespaceConverters.firstNotNullOfOrNull { it.toCAIP2(network) }
- if (chainId == null || address == null) return null
- return CAIP10(chainId = chainId, accountAddress = address)
- }
-
private data class Session(
val chains: MutableSet = mutableSetOf(),
val accounts: MutableSet = mutableSetOf(),
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt
index 91951d8f48..bfd1192118 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt
@@ -49,7 +49,7 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
val pairResult = sdkDelegate.pair(uri)
.onLeft {
Timber.tag(WC_TAG).e(it, "Failed to call pair $pairRequest")
- analytics.send(WcAnalyticEvents.PairFailed)
+ analytics.send(WcAnalyticEvents.PairFailed(it.code))
emit(WcPairState.Error(it))
}
.getOrNull() ?: return@flow
@@ -65,7 +65,7 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
val proposalState = buildProposalState(sdkSessionProposal, sdkVerifyContext)
.onLeft {
- analytics.send(WcAnalyticEvents.PairFailed)
+ analytics.send(WcAnalyticEvents.PairFailed(it.code))
emit(WcPairState.Error(it))
}
.getOrNull() ?: return@flow
@@ -115,6 +115,7 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
}.onCompletion {
if (it != null) {
Timber.tag(WC_TAG).e(it, "Completed with error $pairRequest")
+ emit(WcPairState.Error(WcPairError.Unknown(it.message.orEmpty())))
} else {
Timber.tag(WC_TAG).i("Completed successfully $pairRequest")
}
@@ -134,7 +135,7 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
private suspend fun walletKitApproveSession(
sessionForApprove: WcSessionApprove,
sdkSessionProposal: Wallet.Model.SessionProposal,
- ): Either {
+ ): Either = try {
val namespaces = caipNamespaceDelegate.associate(
sdkSessionProposal,
sessionForApprove,
@@ -143,7 +144,10 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
proposerPublicKey = sdkSessionProposal.proposerPublicKey,
namespaces = namespaces,
)
- return sdkDelegate.approve(sessionApprove)
+ sdkDelegate.approve(sessionApprove)
+ } catch (e: Throwable) {
+ Timber.tag(WC_TAG).e(e, "Failed to sdk approve session $pairRequest")
+ WcPairError.ApprovalFailed(e.message.orEmpty()).left()
}
private suspend fun buildProposalState(
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/WcPairSdkDelegate.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/WcPairSdkDelegate.kt
index e115bb7807..e9665c0673 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/WcPairSdkDelegate.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/WcPairSdkDelegate.kt
@@ -150,7 +150,7 @@ internal class WcPairSdkDelegate : WcSdkObserver {
private fun Throwable.toApproveError() = WcPairError.ApprovalFailed(this.localizedMessage.orEmpty()).left()
companion object {
- private const val CALLBACK_TIMEOUT = 30
+ private const val CALLBACK_TIMEOUT = 60
// com.reown.android.pairing.engine.domain.PairingEngine.pair
private val pairingExpiredMessages = listOf(
"Pairing URI expired",
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/request/DefaultWcRequestUseCaseFactory.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/request/DefaultWcRequestUseCaseFactory.kt
index 53ad5c917a..31791fd91c 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/request/DefaultWcRequestUseCaseFactory.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/request/DefaultWcRequestUseCaseFactory.kt
@@ -3,10 +3,14 @@ package com.tangem.data.walletconnect.request
import arrow.core.Either
import arrow.core.left
import arrow.core.right
+import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.data.walletconnect.utils.WC_TAG
+import com.tangem.data.walletconnect.utils.WcNamespaceConverter
+import com.tangem.domain.walletconnect.WcAnalyticEvents
import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
import com.tangem.domain.walletconnect.model.HandleMethodError
import com.tangem.domain.walletconnect.model.WcMethod
+import com.tangem.domain.walletconnect.model.WcRequestError.Companion.code
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
import timber.log.Timber
@@ -14,6 +18,8 @@ import javax.inject.Inject
internal class DefaultWcRequestUseCaseFactory @Inject constructor(
private val requestConverters: Set,
+ private val namespaceConverters: Set,
+ private val analytics: AnalyticsEventHandler,
) : WcRequestUseCaseFactory {
@Suppress("UNCHECKED_CAST")
@@ -25,12 +31,26 @@ internal class DefaultWcRequestUseCaseFactory @Inject constructor(
?.toUseCase(request)
?: HandleMethodError.UnknownError("Failed to create WcUseCase").left()
- return useCase.fold(
+ val result = useCase.fold(
ifLeft = {
Timber.tag(WC_TAG).e("$it")
it.left()
},
ifRight = { (it as? T)?.right() ?: HandleMethodError.Unsupported(WcMethod.Unsupported(request)).left() },
)
+ result.onLeft { logError(it, request) }
+ return result
+ }
+
+ private fun logError(error: HandleMethodError, request: WcSdkSessionRequest) {
+ val blockchainName = namespaceConverters
+ .firstNotNullOfOrNull { it.toBlockchain(request.chainId.orEmpty()) }
+ ?.getCoinName().orEmpty()
+ val event = WcAnalyticEvents.SignatureRequestReceivedFailed(
+ rawRequest = request,
+ errorCode = error.code().orEmpty(),
+ blockchain = blockchainName,
+ )
+ analytics.send(event)
}
}
\ No newline at end of file
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt
index 614d12dc9c..38ed978e2d 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt
@@ -52,7 +52,7 @@ internal class DefaultWcSessionsManager(
if (someMigrated) return@transform // ignore emit, wait next one
}
val associatedSessions: List = associate(inSdk, inStore, wallets)
- val someRemove = removeUnknownSessions(inStore, associatedSessions)
+ val someRemove = removeUnknownSessions(inStore, inSdk, associatedSessions)
if (someRemove) return@transform // ignore emit, wait next one
emit(associatedSessions.groupBy { it.wallet })
}
@@ -79,7 +79,7 @@ internal class DefaultWcSessionsManager(
override suspend fun removeSession(session: WcSession): Either {
val topic = session.sdkModel.topic
val sdkCall = sdkDisconnectSession(topic)
- .onRight { onSessionDelete.trySend(Wallet.Model.SessionDelete.Success(topic = topic, reason = "")) }
+ onSessionDelete.trySend(Wallet.Model.SessionDelete.Success(topic = topic, reason = ""))
analytics.send(WcAnalyticEvents.SessionDisconnected(session.sdkModel.appMetaData))
return sdkCall
}
@@ -142,10 +142,17 @@ internal class DefaultWcSessionsManager(
return wcSessions
}
- private suspend fun removeUnknownSessions(storeSessions: Set, wcSessions: List): Boolean {
+ private suspend fun removeUnknownSessions(
+ storeSessions: Set,
+ inSdkSessions: List,
+ wcSessions: List,
+ ): Boolean {
val unknownStoredSessions = storeSessions
.filterNot { dto -> wcSessions.any { it.sdkModel.topic == dto.topic } }
val haveSomeUnknown = unknownStoredSessions.isNotEmpty()
+ val unknownSdkSessions = inSdkSessions
+ .filterNot { sdkSession -> wcSessions.any { it.sdkModel.topic == sdkSession.topic } }
+ val haveSomeUnknownSdkSessions = unknownSdkSessions.isNotEmpty()
if (haveSomeUnknown) {
Timber.tag(WC_TAG).i("removeUnknownSessions $unknownStoredSessions")
@@ -164,7 +171,10 @@ internal class DefaultWcSessionsManager(
store.removeSessions(emptyNetworksDto)
}
if (haveEmptySessions) {
- emptyNetworkSessions.map { scope.launch { sdkDisconnectSession(it.sdkModel.topic) } }
+ emptyNetworkSessions.forEach { scope.launch { sdkDisconnectSession(it.sdkModel.topic) } }
+ }
+ if (haveSomeUnknownSdkSessions) {
+ unknownSdkSessions.forEach { scope.launch { sdkDisconnectSession(it.topic) } }
}
return haveSomeUnknown || haveEmptyDto
}
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt
index 2dea8ba415..af4f00d088 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt
@@ -43,7 +43,6 @@ internal class WcSignUseCaseDelegate(
val state = MutableStateFlow(WcSignState(initModel, WcSignStep.PreSign))
analytics.send(
WcAnalyticEvents.SignatureRequestReceived(
- session = context.session,
rawRequest = context.rawSdkRequest,
network = context.network,
),
@@ -73,7 +72,6 @@ internal class WcSignUseCaseDelegate(
val event = step.result.fold(
ifLeft = { error ->
WcAnalyticEvents.SignatureRequestFailed(
- session = context.session,
rawRequest = context.rawSdkRequest,
network = context.network,
errorCode = error.code() ?: error::class.simpleName.orEmpty(),
@@ -81,7 +79,6 @@ internal class WcSignUseCaseDelegate(
},
ifRight = {
WcAnalyticEvents.SignatureRequestHandled(
- session = context.session,
rawRequest = context.rawSdkRequest,
network = context.network,
)
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNamespaceConverter.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNamespaceConverter.kt
index 5d12294eed..a65c47d3df 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNamespaceConverter.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNamespaceConverter.kt
@@ -16,7 +16,6 @@ internal interface WcNamespaceConverter {
fun toBlockchain(chainId: CAIP2): Blockchain?
fun toBlockchain(chainId: String): Blockchain? = toCAIP2(chainId)?.let { caip2 -> toBlockchain(caip2) }
- fun toCAIP2(network: Network): CAIP2?
fun toCAIP2(chainId: String): CAIP2? = CAIP2.fromRaw(chainId)
fun toNetwork(chainId: String, wallet: UserWallet): Network? {
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcSdkSessionRequestConverter.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcSdkSessionRequestConverter.kt
index 603699848e..3c0fd55daa 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcSdkSessionRequestConverter.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcSdkSessionRequestConverter.kt
@@ -10,6 +10,8 @@ internal object WcSdkSessionRequestConverter : Converter,
) : SimulationData()
+
+ /**
+ * Simulation was successfully performed and no changes detected
+ */
+ data object NoWalletChangesDetected : SimulationData()
}
\ No newline at end of file
diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/actions/BaseActionsFactory.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/actions/BaseActionsFactory.kt
index 5863373ebf..ae077ffd24 100644
--- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/actions/BaseActionsFactory.kt
+++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/actions/BaseActionsFactory.kt
@@ -173,7 +173,7 @@ internal open class BaseActionsFactory(
}
}
- private fun getReceiveScenario(requirements: AssetRequirementsCondition?): ScenarioUnavailabilityReason {
+ protected fun getReceiveScenario(requirements: AssetRequirementsCondition?): ScenarioUnavailabilityReason {
return when (requirements) {
AssetRequirementsCondition.PaidTransaction,
is AssetRequirementsCondition.PaidTransactionWithFee,
diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/actions/CommonActionsFactory.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/actions/CommonActionsFactory.kt
index 522690bc10..05b1e1969e 100644
--- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/actions/CommonActionsFactory.kt
+++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/actions/CommonActionsFactory.kt
@@ -8,6 +8,7 @@ import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.staking.model.StakingAvailability
import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason
import com.tangem.domain.tokens.model.TokenActionsState.ActionState
+import com.tangem.domain.transaction.models.AssetRequirementsCondition
import com.tangem.domain.walletmanager.WalletManagersFacade
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
@@ -65,6 +66,7 @@ internal class CommonActionsFactory(
getSwapUnavailabilityReason(
userWalletId = userWallet.walletId,
currency = cryptoCurrencyStatus.currency,
+ requirementsDeferred = requirementsDeferred,
)
}
} else {
@@ -170,7 +172,16 @@ internal class CommonActionsFactory(
private suspend fun getSwapUnavailabilityReason(
userWalletId: UserWalletId,
currency: CryptoCurrency,
+ requirementsDeferred: Deferred?,
): ScenarioUnavailabilityReason {
- return rampStateManager.availableForSwap(userWalletId = userWalletId, cryptoCurrency = currency)
+ val swapUnavailabilityReason = rampStateManager
+ .availableForSwap(userWalletId = userWalletId, cryptoCurrency = currency)
+ val shouldCheckAssetRequirements =
+ swapUnavailabilityReason == ScenarioUnavailabilityReason.None && requirementsDeferred != null
+ return if (shouldCheckAssetRequirements) {
+ getReceiveScenario(requirementsDeferred.await())
+ } else {
+ swapUnavailabilityReason
+ }
}
}
\ No newline at end of file
diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcAppMetaData.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcAppMetaData.kt
index f8de996d34..4b5d5c4475 100644
--- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcAppMetaData.kt
+++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcAppMetaData.kt
@@ -1,8 +1,11 @@
package com.tangem.domain.walletconnect.model.sdkcopy
+import kotlinx.serialization.Serializable
+
/**
* copy of [com.reown.android.Core.Model.AppMetaData]
*/
+@Serializable
data class WcAppMetaData(
val name: String,
val description: String,
diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcSdkSessionRequest.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcSdkSessionRequest.kt
index 02240181d0..7892491554 100644
--- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcSdkSessionRequest.kt
+++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcSdkSessionRequest.kt
@@ -9,6 +9,7 @@ import kotlinx.serialization.Serializable
data class WcSdkSessionRequest(
val topic: String,
val chainId: String?,
+ val dAppMetaData: WcAppMetaData,
val request: JSONRPCRequest,
) {
diff --git a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcAnalyticEvents.kt b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcAnalyticEvents.kt
index cb8f983b1f..fa4b050106 100644
--- a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcAnalyticEvents.kt
+++ b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcAnalyticEvents.kt
@@ -49,8 +49,13 @@ sealed class WcAnalyticEvents(
),
)
- data object PairFailed : WcAnalyticEvents(
+ class PairFailed(
+ errorCode: String,
+ ) : WcAnalyticEvents(
event = "Session Failed",
+ params = mapOf(
+ AnalyticsParam.Key.ERROR_CODE to errorCode,
+ ),
)
class DAppConnected(
@@ -83,49 +88,61 @@ sealed class WcAnalyticEvents(
)
class SignatureRequestReceived(
- session: WcSession,
rawRequest: WcSdkSessionRequest,
network: Network,
) : WcAnalyticEvents(
event = "Signature Request Received",
params = mapOf(
- AnalyticsParam.Key.DAPP_NAME to session.sdkModel.appMetaData.name,
- AnalyticsParam.Key.DAPP_URL to session.sdkModel.appMetaData.url,
+ AnalyticsParam.Key.DAPP_NAME to rawRequest.dAppMetaData.name,
+ AnalyticsParam.Key.DAPP_URL to rawRequest.dAppMetaData.url,
AnalyticsParam.Key.METHOD_NAME to rawRequest.request.method,
AnalyticsParam.Key.BLOCKCHAIN to network.name,
),
)
class SignatureRequestHandled(
- session: WcSession,
rawRequest: WcSdkSessionRequest,
network: Network,
) : WcAnalyticEvents(
event = "Signature Request Handled",
params = mapOf(
- AnalyticsParam.Key.DAPP_NAME to session.sdkModel.appMetaData.name,
- AnalyticsParam.Key.DAPP_URL to session.sdkModel.appMetaData.url,
+ AnalyticsParam.Key.DAPP_NAME to rawRequest.dAppMetaData.name,
+ AnalyticsParam.Key.DAPP_URL to rawRequest.dAppMetaData.url,
AnalyticsParam.Key.METHOD_NAME to rawRequest.request.method,
AnalyticsParam.Key.BLOCKCHAIN to network.name,
),
)
class SignatureRequestFailed(
- session: WcSession,
rawRequest: WcSdkSessionRequest,
network: Network,
errorCode: String,
) : WcAnalyticEvents(
event = "Signature Request Failed",
params = mapOf(
- AnalyticsParam.Key.DAPP_NAME to session.sdkModel.appMetaData.name,
- AnalyticsParam.Key.DAPP_URL to session.sdkModel.appMetaData.url,
+ AnalyticsParam.Key.DAPP_NAME to rawRequest.dAppMetaData.name,
+ AnalyticsParam.Key.DAPP_URL to rawRequest.dAppMetaData.url,
AnalyticsParam.Key.METHOD_NAME to rawRequest.request.method,
AnalyticsParam.Key.BLOCKCHAIN to network.name,
AnalyticsParam.Key.ERROR_CODE to errorCode,
),
)
+ class SignatureRequestReceivedFailed(
+ rawRequest: WcSdkSessionRequest,
+ blockchain: String,
+ errorCode: String,
+ ) : WcAnalyticEvents(
+ event = "Signature Request Received with Failed",
+ params = mapOf(
+ AnalyticsParam.Key.DAPP_NAME to rawRequest.dAppMetaData.name,
+ AnalyticsParam.Key.DAPP_URL to rawRequest.dAppMetaData.url,
+ AnalyticsParam.Key.METHOD_NAME to rawRequest.request.method,
+ AnalyticsParam.Key.BLOCKCHAIN to blockchain,
+ AnalyticsParam.Key.ERROR_CODE to errorCode,
+ ),
+ )
+
class ButtonSign(
rawRequest: WcSdkSessionRequest,
) : WcAnalyticEvents(
diff --git a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcTransactionUseCase.kt b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcTransactionUseCase.kt
index acc4686c4d..af7e9c585f 100644
--- a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcTransactionUseCase.kt
+++ b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcTransactionUseCase.kt
@@ -34,7 +34,7 @@ interface WcListTransactionUseCase :
* [updateFee] triggered a new [TransactionData] emit
*/
interface WcMutableFee {
- fun dAppFee(): Fee?
+ suspend fun dAppFee(): Fee?
fun updateFee(fee: Fee)
}
diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/model/OnrampRedirectModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/model/OnrampRedirectModel.kt
index d19b0fc95b..01c26e0e76 100644
--- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/model/OnrampRedirectModel.kt
+++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/model/OnrampRedirectModel.kt
@@ -85,7 +85,13 @@ internal class OnrampRedirectModel @Inject constructor(
.onLeft(::handleError)
.onRight {
latestOnrampTransaction = it
- urlOpener.openUrl(it.redirectUrl)
+
+ // Workaround to open Unlimit provider in external browser instead of chrome custom tabs
+ if (params.onrampProviderWithQuote.provider.id.equals(UNLIMIT_PROVIDER_ID, ignoreCase = true)) {
+ urlOpener.openUrlExternalBrowser(it.redirectUrl)
+ } else {
+ urlOpener.openUrl(it.redirectUrl)
+ }
}
}
}
@@ -126,4 +132,8 @@ internal class OnrampRedirectModel @Inject constructor(
messageSender.send(message)
}
+
+ private companion object {
+ const val UNLIMIT_PROVIDER_ID = "unlimit"
+ }
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/AlertsComponentV2.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/AlertsComponentV2.kt
index 78ea021b35..db7a6f0f00 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/AlertsComponentV2.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/AlertsComponentV2.kt
@@ -12,6 +12,7 @@ internal class AlertsComponentV2(
) : AppComponentContext by appComponentContext, ComposableBottomSheetComponent {
override fun dismiss() {
+ messageUM.onDismissRequest()
router.pop()
}
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcPairComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcPairComponent.kt
index 675c063840..a171a0f38a 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcPairComponent.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcPairComponent.kt
@@ -115,8 +115,11 @@ internal class WcPairComponent(
is Alert.Type.Verified -> WcAlertsFactory.createVerifiedDomainAlert(alertType.appName)
is Alert.Type.UnknownDomain -> WcAlertsFactory.createUnknownDomainAlert(model::connectFromAlert)
is Alert.Type.UnsafeDomain -> WcAlertsFactory.createUnsafeDomainAlert(model::connectFromAlert)
- is Alert.Type.UnsupportedDApp -> WcAlertsFactory.createUnsupportedDomainAlert(alertType.appName)
- is Alert.Type.UnsupportedNetwork -> WcAlertsFactory.createUnsupportedChainAlert(alertType.appName)
+ is Alert.Type.UnsupportedDApp ->
+ WcAlertsFactory.createUnsupportedDomainAlert(alertType.appName, model::errorAlertOnDismiss)
+ is Alert.Type.UnsupportedNetwork ->
+ WcAlertsFactory.createUnsupportedChainAlert(alertType.appName, model::errorAlertOnDismiss)
+ is Alert.Type.UriAlreadyUsed -> WcAlertsFactory.createUriAlreadyUsedAlert(model::errorAlertOnDismiss)
}
}
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt
index f92ac32008..c745515dc4 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt
@@ -149,6 +149,10 @@ internal class WcPairModel @Inject constructor(
connect()
}
+ fun errorAlertOnDismiss() {
+ router.pop()
+ }
+
private fun onConnect(securityStatus: CheckDAppResult) {
when (securityStatus) {
CheckDAppResult.SAFE -> connect()
@@ -193,16 +197,23 @@ internal class WcPairModel @Inject constructor(
}
private fun processError(error: WcPairError) {
- when (error) {
+ val alert = when (error) {
is WcPairError.UnsupportedDApp -> {
WcAppInfoRoutes.Alert.Type.UnsupportedDApp(error.appName)
}
is WcPairError.UnsupportedBlockchains -> {
WcAppInfoRoutes.Alert.Type.UnsupportedNetwork(error.appName)
}
- else -> null
- }?.let { stackNavigation.pushNew(WcAppInfoRoutes.Alert(it)) }
- ?: run { messageSender.send(ToastMessage(message = stringReference(error.message))) }
+ is WcPairError.UriAlreadyUsed -> {
+ WcAppInfoRoutes.Alert.Type.UriAlreadyUsed
+ }
+ else -> {
+ messageSender.send(ToastMessage(message = stringReference(error.message)))
+ router.pop()
+ null
+ }
+ }
+ alert?.let { stackNavigation.pushNew(WcAppInfoRoutes.Alert(it)) }
}
override fun onWalletSelected(userWalletId: UserWalletId) {
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routes/WcAppInfoRoutes.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routes/WcAppInfoRoutes.kt
index 56215acac5..cf5b226353 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routes/WcAppInfoRoutes.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routes/WcAppInfoRoutes.kt
@@ -34,6 +34,7 @@ internal sealed class WcAppInfoRoutes : TangemBottomSheetConfigContent, Route {
data object UnsafeDomain : Type()
data class UnsupportedDApp(val appName: String) : Type()
data class UnsupportedNetwork(val appName: String) : Type()
+ data object UriAlreadyUsed : Type()
}
}
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoBS.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoBS.kt
index 9804255452..af9a95cdf2 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoBS.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoBS.kt
@@ -22,6 +22,7 @@ import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
@@ -311,23 +312,28 @@ private fun WalletRowItem(walletName: String, showEndIcon: Boolean, modifier: Mo
contentDescription = null,
tint = TangemTheme.colors.icon.accent,
)
- Text(
- modifier = Modifier
- .padding(start = TangemTheme.dimens.spacing4)
- .weight(1f),
- text = stringResourceSafe(R.string.manage_tokens_network_selector_wallet),
- style = TangemTheme.typography.body1,
- color = TangemTheme.colors.text.primary1,
- )
- Text(
- modifier = Modifier
- .padding(start = TangemTheme.dimens.spacing16)
- .weight(1f),
- text = walletName,
- textAlign = TextAlign.End,
- style = TangemTheme.typography.body1,
- color = TangemTheme.colors.text.tertiary,
- )
+ Row(
+ modifier = Modifier.weight(1f),
+ horizontalArrangement = Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Text(
+ modifier = Modifier.padding(start = TangemTheme.dimens.spacing4),
+ text = stringResourceSafe(R.string.manage_tokens_network_selector_wallet),
+ style = TangemTheme.typography.body1,
+ color = TangemTheme.colors.text.primary1,
+ maxLines = 1,
+ )
+ Text(
+ modifier = Modifier.padding(start = TangemTheme.dimens.spacing16),
+ text = walletName,
+ textAlign = TextAlign.End,
+ style = TangemTheme.typography.body1,
+ color = TangemTheme.colors.text.tertiary,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ )
+ }
if (showEndIcon) {
Icon(
modifier = Modifier
@@ -611,7 +617,7 @@ private class WcAppInfoStateProvider : CollectionPreviewParameterProvider
createUnsafeDomainAlert()
- is WcTransactionRoutes.Alert.Type.MaliciousInfo ->
- createMaliciousDAppAlert(alertType.description, alertType.onClick)
+ is WcTransactionRoutes.Alert.Type.BlockAidErrorInfo ->
+ createMaliciousDAppAlert(alertType.description, alertType.onClick, alertType.iconType, alertType.iconBgType)
is WcTransactionRoutes.Alert.Type.UnknownError ->
- createUnknownErrorAlert(alertType.errorMessage, alertType.onDismiss)
+ createUnknownErrorAlert(alertType.errorMessage, alertType.onDismiss, alertType.onRetry)
}
fun createUnknownDomainAlert(activeButtonOnClick: (() -> Unit)? = null): MessageBottomSheetUMV2 {
@@ -74,11 +74,11 @@ internal object WcAlertsFactory {
}
}
- fun createUnsupportedDomainAlert(appName: String): MessageBottomSheetUMV2 {
+ fun createUnsupportedDomainAlert(appName: String, onDismiss: () -> Unit): MessageBottomSheetUMV2 {
return messageBottomSheetUM {
infoBlock {
icon(R.drawable.ic_wallet_connect_24) {
- type = MessageBottomSheetUMV2.Icon.Type.Informative
+ type = Type.Informative
backgroundType = MessageBottomSheetUMV2.Icon.BackgroundType.SameAsTint
}
title = resourceReference(R.string.wc_alert_unsupported_dapps_title)
@@ -86,16 +86,34 @@ internal object WcAlertsFactory {
}
primaryButton {
text = resourceReference(R.string.common_got_it)
- onClick { closeBs() }
+ onClick { onDismiss() }
+ }
+ onDismissRequest = onDismiss
+ }
+ }
+
+ fun createUriAlreadyUsedAlert(onDismiss: () -> Unit): MessageBottomSheetUMV2 {
+ return messageBottomSheetUM {
+ infoBlock {
+ icon(R.drawable.ic_wallet_connect_24) {
+ type = Type.Informative
+ backgroundType = MessageBottomSheetUMV2.Icon.BackgroundType.SameAsTint
+ }
+ title = resourceReference(R.string.wc_uri_already_used_title)
+ body = resourceReference(R.string.wc_uri_already_used_description)
+ }
+ primaryButton {
+ text = resourceReference(R.string.common_got_it)
+ onClick { onDismiss() }
}
}
}
- fun createUnsupportedChainAlert(appName: String): MessageBottomSheetUMV2 {
+ fun createUnsupportedChainAlert(appName: String, onDismiss: () -> Unit): MessageBottomSheetUMV2 {
return messageBottomSheetUM {
infoBlock {
icon(R.drawable.ic_network_new_24) {
- type = MessageBottomSheetUMV2.Icon.Type.Informative
+ type = Type.Informative
backgroundType = MessageBottomSheetUMV2.Icon.BackgroundType.SameAsTint
}
title = resourceReference(R.string.wc_alert_unsupported_networks_title)
@@ -103,12 +121,17 @@ internal object WcAlertsFactory {
}
primaryButton {
text = resourceReference(R.string.common_got_it)
- onClick { closeBs() }
+ onClick { onDismiss() }
}
+ onDismissRequest = onDismiss
}
}
- private fun createUnknownErrorAlert(errorMessage: String?, onDismiss: () -> Unit): MessageBottomSheetUMV2 {
+ private fun createUnknownErrorAlert(
+ errorMessage: String?,
+ onDismiss: () -> Unit,
+ onRetry: () -> Unit,
+ ): MessageBottomSheetUMV2 {
return messageBottomSheetUM {
infoBlock {
icon(R.drawable.img_attention_20) {
@@ -124,21 +147,29 @@ internal object WcAlertsFactory {
)
}
}
+ primaryButton {
+ text = resourceReference(R.string.alert_button_try_again)
+ onClick { onRetry() }
+ }
secondaryButton {
- text = resourceReference(R.string.balance_hidden_got_it_button)
+ text = resourceReference(R.string.common_cancel)
onClick { onDismiss() }
}
+ onDismissRequest = onDismiss
}
}
private fun createMaliciousDAppAlert(
description: String?,
activeButtonOnClick: (() -> Unit),
+ iconType: Type,
+ iconBgType: MessageBottomSheetUMV2.Icon.BackgroundType,
): MessageBottomSheetUMV2 {
return messageBottomSheetUM {
infoBlock {
icon(R.drawable.img_knight_shield_32) {
- backgroundType = MessageBottomSheetUMV2.Icon.BackgroundType.Attention
+ type = iconType
+ backgroundType = iconBgType
}
title = resourceReference(R.string.security_alert_title)
if (!description.isNullOrEmpty()) {
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/send/WcSendTransactionComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/send/WcSendTransactionComponent.kt
index eb105f2216..62f838c9b7 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/send/WcSendTransactionComponent.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/send/WcSendTransactionComponent.kt
@@ -7,6 +7,7 @@ import com.arkivanov.essenty.lifecycle.doOnResume
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.features.send.v2.api.FeeSelectorBlockComponent
+import com.tangem.features.send.v2.api.entity.FeeSelectorUM
import com.tangem.features.send.v2.api.params.FeeSelectorParams
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionFeeState
import com.tangem.features.walletconnect.transaction.model.WcSendTransactionModel
@@ -58,6 +59,7 @@ internal class WcSendTransactionComponent(
WcSendTransactionModalBottomSheet(
state = state,
feeSelectorBlockComponent = feeSelectorBlock,
+ feeSelectorUM = content?.feeSelectorUM ?: FeeSelectorUM.Loading,
onClickTransactionRequest = model::showTransactionRequest,
onBack = router::pop,
onDismiss = ::dismiss,
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcAddressConverter.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcAddressConverter.kt
index cbcc897ce4..4e9838e99c 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcAddressConverter.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcAddressConverter.kt
@@ -1,24 +1,14 @@
package com.tangem.features.walletconnect.transaction.converter
import com.tangem.domain.walletconnect.usecase.method.WcNetworkDerivationState
-import com.tangem.features.walletconnect.transaction.entity.common.WcAddressUM
import com.tangem.utils.converter.Converter
-private const val ADDRESS_FIRST_PART_LENGTH = 7
-private const val ADDRESS_SECOND_PART_LENGTH = 4
+internal object WcAddressConverter : Converter {
-internal object WcAddressConverter : Converter {
-
- override fun convert(value: WcNetworkDerivationState): WcAddressUM? {
+ override fun convert(value: WcNetworkDerivationState): String? {
return when (value) {
is WcNetworkDerivationState.Single -> null
- is WcNetworkDerivationState.Multiple -> WcAddressUM(
- fullAddress = value.walletAddress,
- shortAddress = value.walletAddress.toShortAddressText(),
- )
+ is WcNetworkDerivationState.Multiple -> value.walletAddress
}
}
-
- private fun String.toShortAddressText() =
- "${take(ADDRESS_FIRST_PART_LENGTH)}...${takeLast(ADDRESS_SECOND_PART_LENGTH)}"
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcCommonTransactionUMConverter.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcCommonTransactionUMConverter.kt
deleted file mode 100644
index 84d4f29ebc..0000000000
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcCommonTransactionUMConverter.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.tangem.features.walletconnect.transaction.converter
-
-import com.tangem.domain.walletconnect.model.WcEthMethod
-import com.tangem.domain.walletconnect.model.WcSolanaMethod
-import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
-import com.tangem.domain.walletconnect.usecase.method.WcSignState
-import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase
-import com.tangem.domain.walletconnect.usecase.method.WcTransactionUseCase
-import com.tangem.features.send.v2.api.entity.FeeSelectorUM
-import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionUM
-import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
-import com.tangem.utils.converter.Converter
-import javax.inject.Inject
-
-internal class WcCommonTransactionUMConverter @Inject constructor(
- private val signTypedDataUMConverter: WcSignTypedDataUMConverter,
- private val signTransactionUMConverter: WcSignTransactionUMConverter,
- private val sendTransactionUMConverter: WcSendTransactionUMConverter,
-) : Converter {
-
- override fun convert(value: Input): WcCommonTransactionUM? {
- return when (value.useCase) {
- is WcMessageSignUseCase -> {
- when (value.useCase.method) {
- is WcEthMethod.SignTypedData -> signTypedDataUMConverter.convert(
- WcSignTypedDataUMConverter.Input(
- useCase = value.useCase,
- signState = value.signState,
- signModel = value.signState.signModel as WcMessageSignUseCase.SignModel,
- actions = value.actions,
- ),
- )
- is WcEthMethod.MessageSign, is WcSolanaMethod.SignMessage -> signTransactionUMConverter.convert(
- WcSignTransactionUMConverter.Input(
- useCase = value.useCase,
- signState = value.signState,
- signModel = value.signState.signModel as WcMessageSignUseCase.SignModel,
- actions = value.actions,
- ),
- )
- else -> null
- }
- }
- is WcTransactionUseCase -> sendTransactionUMConverter.convert(
- WcSendTransactionUMConverter.Input(
- useCase = value.useCase,
- signState = value.signState,
- actions = value.actions,
- feeSelectorUM = value.feeSelectorUM,
- ),
- )
- else -> null
- }
- }
-
- data class Input(
- val useCase: WcSignUseCase<*>,
- val signState: WcSignState<*>,
- val actions: WcTransactionActionsUM,
- val feeSelectorUM: FeeSelectorUM? = null,
- )
-}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSendTransactionUMConverter.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSendTransactionUMConverter.kt
index 9a2275f2d4..348a69439e 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSendTransactionUMConverter.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSendTransactionUMConverter.kt
@@ -1,8 +1,11 @@
package com.tangem.features.walletconnect.transaction.converter
+import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.walletconnect.model.WcEthMethod
import com.tangem.domain.walletconnect.model.WcSolanaMethod
-import com.tangem.domain.walletconnect.usecase.method.*
+import com.tangem.domain.walletconnect.usecase.method.WcMethodContext
+import com.tangem.domain.walletconnect.usecase.method.WcSignState
+import com.tangem.domain.walletconnect.usecase.method.WcSignStep
import com.tangem.features.send.v2.api.entity.FeeSelectorUM
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
@@ -10,6 +13,7 @@ import com.tangem.features.walletconnect.transaction.entity.common.WcTransaction
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoUM
import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionItemUM
import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionUM
+import com.tangem.features.walletconnect.utils.WcNotificationsFactory
import com.tangem.utils.converter.Converter
import kotlinx.collections.immutable.toImmutableList
import javax.inject.Inject
@@ -18,58 +22,62 @@ internal class WcSendTransactionUMConverter @Inject constructor(
private val appInfoContentUMConverter: WcTransactionAppInfoContentUMConverter,
private val networkInfoUMConverter: WcNetworkInfoUMConverter,
private val requestBlockUMConverter: WcTransactionRequestBlockUMConverter,
+ private val notificationsFactory: WcNotificationsFactory,
) : Converter {
- override fun convert(value: Input): WcSendTransactionUM? = when (value.useCase.method) {
- is WcEthMethod.SendTransaction,
- is WcEthMethod.SignTransaction,
- is WcSolanaMethod.SignAllTransaction,
- is WcSolanaMethod.SignTransaction,
- -> WcSendTransactionUM(
- transaction = WcSendTransactionItemUM(
- onDismiss = value.actions.onDismiss,
- onSend = value.actions.onSign,
- appInfo = appInfoContentUMConverter.convert(
- WcTransactionAppInfoContentUMConverter.Input(
- session = value.useCase.session,
- onShowVerifiedAlert = value.actions.onShowVerifiedAlert,
- ),
- ),
- feeState = constructFeeState(useCase = value.useCase, actions = value.actions),
- walletName = value.useCase.session.wallet.name.takeIf { value.useCase.session.showWalletInfo },
- networkInfo = networkInfoUMConverter.convert(value.useCase.network),
- estimatedWalletChanges = WcSendReceiveTransactionCheckResultsUM(),
- isLoading = value.signState.domainStep == WcSignStep.Signing,
- address = WcAddressConverter.convert(value.useCase.derivationState),
- ),
- feeSelectorUM = value.feeSelectorUM ?: FeeSelectorUM.Loading,
- transactionRequestInfo = WcTransactionRequestInfoUM(
- blocks = buildList {
- addAll(
- requestBlockUMConverter.convert(
- WcTransactionRequestBlockUMConverter.Input(value.useCase.rawSdkRequest),
- ),
- )
- }.toImmutableList(),
- onCopy = value.actions.onCopy,
- ),
+ override fun convert(value: Input): WcSendTransactionUM? {
+ val feeErrorNotification = notificationsFactory.createFeeNotifications(
+ cryptoCurrencyStatus = value.cryptoCurrencyStatus,
+ feeSelectorUM = value.feeSelectorUM,
+ onFeeReload = value.onFeeReload,
)
- else -> null
- }
-
- private fun constructFeeState(
- useCase: WcTransactionUseCase,
- actions: WcTransactionActionsUM,
- ): WcTransactionFeeState {
- val mutableFee = useCase as? WcMutableFee ?: return WcTransactionFeeState.None
- val dAppFee = mutableFee.dAppFee()
- return WcTransactionFeeState.Success(dAppFee = dAppFee, onClick = actions.onShowFeeBottomSheet)
+ return when (value.context.method) {
+ is WcEthMethod.SendTransaction,
+ is WcEthMethod.SignTransaction,
+ is WcSolanaMethod.SignAllTransaction,
+ is WcSolanaMethod.SignTransaction,
+ -> WcSendTransactionUM(
+ transaction = WcSendTransactionItemUM(
+ onDismiss = value.actions.onDismiss,
+ onSend = value.actions.onSign,
+ appInfo = appInfoContentUMConverter.convert(
+ WcTransactionAppInfoContentUMConverter.Input(
+ session = value.context.session,
+ onShowVerifiedAlert = value.actions.onShowVerifiedAlert,
+ ),
+ ),
+ feeState = value.feeState,
+ walletName = value.context.session.wallet.name.takeIf { value.context.session.showWalletInfo },
+ networkInfo = networkInfoUMConverter.convert(value.context.network),
+ estimatedWalletChanges = WcSendReceiveTransactionCheckResultsUM(),
+ isLoading = value.signState.domainStep == WcSignStep.Signing,
+ address = WcAddressConverter.convert(value.context.derivationState),
+ sendEnabled = value.feeSelectorUM is FeeSelectorUM.Content && feeErrorNotification == null,
+ feeErrorNotification = feeErrorNotification,
+ ),
+ feeSelectorUM = value.feeSelectorUM ?: FeeSelectorUM.Loading,
+ transactionRequestInfo = WcTransactionRequestInfoUM(
+ blocks = buildList {
+ addAll(
+ requestBlockUMConverter.convert(
+ WcTransactionRequestBlockUMConverter.Input(value.context.rawSdkRequest),
+ ),
+ )
+ }.toImmutableList(),
+ onCopy = value.actions.onCopy,
+ ),
+ )
+ else -> null
+ }
}
data class Input(
- val useCase: WcTransactionUseCase,
+ val context: WcMethodContext,
+ val feeState: WcTransactionFeeState,
val signState: WcSignState<*>,
val actions: WcTransactionActionsUM,
val feeSelectorUM: FeeSelectorUM?,
+ val cryptoCurrencyStatus: CryptoCurrencyStatus,
+ val onFeeReload: () -> Unit,
)
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSignTransactionUMConverter.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSignTransactionUMConverter.kt
index a1e30fdfad..28368845c9 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSignTransactionUMConverter.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSignTransactionUMConverter.kt
@@ -1,6 +1,7 @@
package com.tangem.features.walletconnect.transaction.converter
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
+import com.tangem.domain.walletconnect.usecase.method.WcMethodContext
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
@@ -23,25 +24,25 @@ internal class WcSignTransactionUMConverter @Inject constructor(
onSign = value.actions.onSign,
appInfo = appInfoContentUMConverter.convert(
WcTransactionAppInfoContentUMConverter.Input(
- session = value.useCase.session,
+ session = value.context.session,
onShowVerifiedAlert = value.actions.onShowVerifiedAlert,
),
),
- walletName = value.useCase.session.wallet.name.takeIf { value.useCase.session.showWalletInfo },
- networkInfo = networkInfoUMConverter.convert(value.useCase.network),
+ walletName = value.context.session.wallet.name.takeIf { value.context.session.showWalletInfo },
+ networkInfo = networkInfoUMConverter.convert(value.context.network),
isLoading = value.signState.domainStep == WcSignStep.Signing,
- address = WcAddressConverter.convert(value.useCase.derivationState),
+ address = WcAddressConverter.convert(value.context.derivationState),
),
transactionRequestInfo = WcTransactionRequestInfoUM(
requestBlockUMConverter.convert(
- WcTransactionRequestBlockUMConverter.Input(value.useCase.rawSdkRequest, value.signModel),
+ WcTransactionRequestBlockUMConverter.Input(value.context.rawSdkRequest, value.signModel),
).toImmutableList(),
onCopy = value.actions.onCopy,
),
)
data class Input(
- val useCase: WcMessageSignUseCase,
+ val context: WcMethodContext,
val signState: WcSignState<*>,
val signModel: WcMessageSignUseCase.SignModel,
val actions: WcTransactionActionsUM,
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSignTypedDataUMConverter.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSignTypedDataUMConverter.kt
index df8661fc77..faef1ed164 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSignTypedDataUMConverter.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/converter/WcSignTypedDataUMConverter.kt
@@ -1,6 +1,7 @@
package com.tangem.features.walletconnect.transaction.converter
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
+import com.tangem.domain.walletconnect.usecase.method.WcMethodContext
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
@@ -23,20 +24,20 @@ internal class WcSignTypedDataUMConverter @Inject constructor(
onSign = value.actions.onSign,
appInfo = appInfoContentUMConverter.convert(
WcTransactionAppInfoContentUMConverter.Input(
- session = value.useCase.session,
+ session = value.context.session,
onShowVerifiedAlert = value.actions.onShowVerifiedAlert,
),
),
- walletName = value.useCase.session.wallet.name.takeIf { value.useCase.session.showWalletInfo },
- networkInfo = networkInfoUMConverter.convert(value.useCase.network),
- address = WcAddressConverter.convert(value.useCase.derivationState),
+ walletName = value.context.session.wallet.name.takeIf { value.context.session.showWalletInfo },
+ networkInfo = networkInfoUMConverter.convert(value.context.network),
+ address = WcAddressConverter.convert(value.context.derivationState),
isLoading = value.signState.domainStep == WcSignStep.Signing,
),
transactionRequestInfo = WcTransactionRequestInfoUM(
blocks = buildList {
addAll(
requestBlockUMConverter.convert(
- WcTransactionRequestBlockUMConverter.Input(value.useCase.rawSdkRequest, value.signModel),
+ WcTransactionRequestBlockUMConverter.Input(value.context.rawSdkRequest, value.signModel),
),
)
}.toImmutableList(),
@@ -45,7 +46,7 @@ internal class WcSignTypedDataUMConverter @Inject constructor(
)
data class Input(
- val useCase: WcMessageSignUseCase,
+ val context: WcMethodContext,
val signState: WcSignState<*>,
val signModel: WcMessageSignUseCase.SignModel,
val actions: WcTransactionActionsUM,
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/blockaid/WcSendReceiveTransactionCheckResultsUM.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/blockaid/WcSendReceiveTransactionCheckResultsUM.kt
index 096af30724..850cfb201e 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/blockaid/WcSendReceiveTransactionCheckResultsUM.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/blockaid/WcSendReceiveTransactionCheckResultsUM.kt
@@ -6,6 +6,17 @@ import com.tangem.features.walletconnect.transaction.entity.approve.WcSpendAllow
internal data class WcSendReceiveTransactionCheckResultsUM(
val estimatedWalletChanges: WcEstimatedWalletChangesUM? = null,
val spendAllowance: WcSpendAllowanceUM? = null,
- val notificationText: TextReference? = null,
+ val notification: BlockAidNotificationUM? = null,
+ val additionalNotification: TextReference? = null,
val isLoading: Boolean = true,
-)
\ No newline at end of file
+)
+
+internal data class BlockAidNotificationUM(
+ val type: Type,
+ val title: TextReference,
+ val text: TextReference? = null,
+) {
+ internal enum class Type {
+ ERROR, WARNING
+ }
+}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/common/WcAddressUM.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/common/WcAddressUM.kt
deleted file mode 100644
index a43b29458a..0000000000
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/common/WcAddressUM.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.tangem.features.walletconnect.transaction.entity.common
-
-data class WcAddressUM(val fullAddress: String, val shortAddress: String)
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/send/WcSendTransactionUM.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/send/WcSendTransactionUM.kt
index b1461cbfd5..86ef260951 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/send/WcSendTransactionUM.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/send/WcSendTransactionUM.kt
@@ -1,10 +1,10 @@
package com.tangem.features.walletconnect.transaction.entity.send
+import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.features.send.v2.api.entity.FeeSelectorUM
import com.tangem.features.walletconnect.transaction.entity.approve.WcSpendAllowanceUM
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
-import com.tangem.features.walletconnect.transaction.entity.common.WcAddressUM
import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionUM
import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionAppInfoContentUM
@@ -26,6 +26,8 @@ internal data class WcSendTransactionItemUM(
val estimatedWalletChanges: WcSendReceiveTransactionCheckResultsUM?,
val walletName: String?,
val networkInfo: WcNetworkInfoUM,
- val address: WcAddressUM?,
+ val address: String?,
+ val sendEnabled: Boolean,
+ val feeErrorNotification: NotificationUM.Info?,
val isLoading: Boolean = false,
) : TangemBottomSheetConfigContent
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/sign/WcSignTransactionUM.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/sign/WcSignTransactionUM.kt
index fd69bf9cb7..54c08cf874 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/sign/WcSignTransactionUM.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/sign/WcSignTransactionUM.kt
@@ -1,7 +1,6 @@
package com.tangem.features.walletconnect.transaction.entity.sign
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
-import com.tangem.features.walletconnect.transaction.entity.common.WcAddressUM
import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionUM
import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionAppInfoContentUM
@@ -18,6 +17,6 @@ internal data class WcSignTransactionItemUM(
val appInfo: WcTransactionAppInfoContentUM,
val walletName: String?,
val networkInfo: WcNetworkInfoUM,
- val address: WcAddressUM?,
+ val address: String?,
val isLoading: Boolean = false,
) : TangemBottomSheetConfigContent
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt
index fc2dac78e4..419551a54d 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt
@@ -15,6 +15,8 @@ import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.ui.clipboard.ClipboardManager
+import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUMV2
+import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUMV2.Icon.Type
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.core.lce.Lce
import com.tangem.domain.models.currency.CryptoCurrencyStatus
@@ -36,14 +38,16 @@ import com.tangem.features.send.v2.api.subcomponents.feeSelector.FeeSelectorRelo
import com.tangem.features.send.v2.api.subcomponents.feeSelector.entity.FeeSelectorData
import com.tangem.features.walletconnect.connections.routing.WcInnerRoute
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
-import com.tangem.features.walletconnect.transaction.converter.WcCommonTransactionUMConverter
import com.tangem.features.walletconnect.transaction.converter.WcHandleMethodErrorConverter
+import com.tangem.features.walletconnect.transaction.converter.WcSendTransactionUMConverter
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionModel
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
+import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionFeeState
import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionUM
import com.tangem.features.walletconnect.transaction.routes.WcTransactionRoutes
import com.tangem.features.walletconnect.transaction.ui.blockaid.WcSendAndReceiveBlockAidUiConverter
+import com.tangem.features.walletconnect.utils.WcNotificationsFactory
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
@@ -62,10 +66,11 @@ internal class WcSendTransactionModel @Inject constructor(
private val router: Router,
private val clipboardManager: ClipboardManager,
private val useCaseFactory: WcRequestUseCaseFactory,
- private val converter: WcCommonTransactionUMConverter,
+ private val converter: WcSendTransactionUMConverter,
private val blockAidUiConverter: WcSendAndReceiveBlockAidUiConverter,
private val getFeeUseCase: GetFeeUseCase,
private val getNetworkCoinUseCase: GetNetworkCoinStatusUseCase,
+ private val notificationsFactory: WcNotificationsFactory,
private val analytics: AnalyticsEventHandler,
) : Model(), WcCommonTransactionModel, FeeSelectorModelCallback {
@@ -137,7 +142,7 @@ internal class WcSendTransactionModel @Inject constructor(
feeReloadState.value = false
modelScope.launch {
feeSelectorReloadTrigger.triggerUpdate(
- feeData = FeeSelectorData(removeSuggestedFee = true),
+ FeeSelectorData(removeSuggestedFee = feeStateConfiguration !is FeeStateConfiguration.Suggestion),
)
}
}
@@ -156,7 +161,20 @@ internal class WcSendTransactionModel @Inject constructor(
* Also handles fee results from FeeSelectorBlockComponent
*/
fun updateFee(feeSelectorUM: FeeSelectorUM) {
- _uiState.update { it?.copy(feeSelectorUM = feeSelectorUM) }
+ val feeErrorNotification = notificationsFactory.createFeeNotifications(
+ cryptoCurrencyStatus = cryptoCurrencyStatus,
+ feeSelectorUM = feeSelectorUM,
+ onFeeReload = ::triggerFeeReload,
+ )
+ _uiState.update {
+ it?.copy(
+ feeSelectorUM = feeSelectorUM,
+ transaction = it.transaction.copy(
+ sendEnabled = feeSelectorUM is FeeSelectorUM.Content && feeErrorNotification == null,
+ feeErrorNotification = feeErrorNotification,
+ ),
+ )
+ }
val fee = (feeSelectorUM as? FeeSelectorUM.Content)?.selectedFeeItem?.fee ?: return
(useCase as? WcMutableFee)?.updateFee(fee)
}
@@ -198,20 +216,31 @@ internal class WcSendTransactionModel @Inject constructor(
is Lce.Error -> WcSendReceiveTransactionCheckResultsUM(isLoading = false)
is Lce.Loading -> WcSendReceiveTransactionCheckResultsUM(isLoading = true)
}
+
+ val feeState = when {
+ useCase is WcMutableFee -> WcTransactionFeeState.Success(
+ dAppFee = useCase.dAppFee(),
+ onClick = ::onShowFeeBottomSheet,
+ )
+ else -> WcTransactionFeeState.None
+ }
+ val actions = WcTransactionActionsUM(
+ onShowVerifiedAlert = ::showVerifiedAlert,
+ onDismiss = { cancel(useCase) },
+ onSign = { onSign(securityCheck.getOrNull()) },
+ onCopy = { copyData(useCase.rawSdkRequest.request.params) },
+ )
var transactionUM = converter.convert(
- WcCommonTransactionUMConverter.Input(
- useCase = useCase,
+ WcSendTransactionUMConverter.Input(
+ context = useCase,
+ feeState = feeState,
signState = signState,
- actions = WcTransactionActionsUM(
- onShowVerifiedAlert = ::showVerifiedAlert,
- onDismiss = { cancel(useCase) },
- onSign = { onSign(securityCheck.getOrNull()) },
- onCopy = { copyData(useCase.rawSdkRequest.request.params) },
- onShowFeeBottomSheet = ::onShowFeeBottomSheet,
- ),
+ actions = actions,
feeSelectorUM = uiState.value?.feeSelectorUM,
+ cryptoCurrencyStatus = cryptoCurrencyStatus,
+ onFeeReload = ::triggerFeeReload,
),
- ) as? WcSendTransactionUM
+ )
transactionUM = transactionUM?.copy(
transaction = transactionUM.transaction.copy(estimatedWalletChanges = blockAidState),
spendAllowance = blockAidState.spendAllowance,
@@ -236,10 +265,10 @@ internal class WcSendTransactionModel @Inject constructor(
}
private fun onSign(securityCheck: BlockAidTransactionCheck.Result?) {
- if (securityCheck?.result?.validation == ValidationResult.UNSAFE) {
- showMaliciousAlert(securityCheck.result.description)
- } else {
- sign()
+ when (securityCheck?.result?.validation) {
+ ValidationResult.UNSAFE -> showMaliciousAlert(securityCheck.result.description)
+ ValidationResult.WARNING -> showWarningAlert(securityCheck.result.description)
+ else -> sign()
}
securityCheck?.result?.validation?.let { securityStatus ->
val event = WcAnalyticEvents.NoticeSecurityAlert(
@@ -250,6 +279,7 @@ internal class WcSendTransactionModel @Inject constructor(
when (securityStatus) {
ValidationResult.SAFE -> Unit
ValidationResult.UNSAFE,
+ ValidationResult.WARNING,
ValidationResult.FAILED_TO_VALIDATE,
-> analytics.send(event)
}
@@ -273,7 +303,22 @@ internal class WcSendTransactionModel @Inject constructor(
}
private fun showMaliciousAlert(description: String?) {
- val type = WcTransactionRoutes.Alert.Type.MaliciousInfo(description = description, onClick = ::signFromAlert)
+ val type = WcTransactionRoutes.Alert.Type.BlockAidErrorInfo(
+ description = description,
+ onClick = ::signFromAlert,
+ iconType = Type.Warning,
+ iconBgType = MessageBottomSheetUMV2.Icon.BackgroundType.Warning,
+ )
+ stackNavigation.pushNew(WcTransactionRoutes.Alert(type))
+ }
+
+ private fun showWarningAlert(description: String?) {
+ val type = WcTransactionRoutes.Alert.Type.BlockAidErrorInfo(
+ description = description,
+ onClick = ::signFromAlert,
+ iconType = Type.Attention,
+ iconBgType = MessageBottomSheetUMV2.Icon.BackgroundType.Attention,
+ )
stackNavigation.pushNew(WcTransactionRoutes.Alert(type))
}
@@ -284,22 +329,24 @@ internal class WcSendTransactionModel @Inject constructor(
private fun signingIsDone(signState: WcSignState<*>, useCase: WcSignUseCase<*>): Boolean {
(signState.domainStep as? WcSignStep.Result)?.result?.let {
- handleSigningError(it, useCase)
- return true
+ return handleSigningError(it, useCase)
}
return false
}
- private fun handleSigningError(result: Either, useCase: WcSignUseCase<*>) {
- if (result.isLeft()) {
+ private fun handleSigningError(result: Either, useCase: WcSignUseCase<*>): Boolean {
+ return if (result.isLeft()) {
val error = WcTransactionRoutes.Alert.Type.UnknownError(
errorMessage = result.leftOrNull()?.message(),
onDismiss = { cancel(useCase) },
+ onRetry = { signFromAlert() },
)
stackNavigation.pushNew(WcTransactionRoutes.Alert(error))
+ false
} else {
showSuccessSignMessage()
router.pop()
+ true
}
}
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt
index 4738a1abaa..cdcb80f9f4 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt
@@ -11,13 +11,16 @@ import com.tangem.core.decompose.navigation.Router
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.ui.clipboard.ClipboardManager
import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
+import com.tangem.domain.walletconnect.model.WcEthMethod
+import com.tangem.domain.walletconnect.model.WcSolanaMethod
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
-import com.tangem.features.walletconnect.transaction.converter.WcCommonTransactionUMConverter
import com.tangem.features.walletconnect.transaction.converter.WcHandleMethodErrorConverter
+import com.tangem.features.walletconnect.transaction.converter.WcSignTransactionUMConverter
+import com.tangem.features.walletconnect.transaction.converter.WcSignTypedDataUMConverter
import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionModel
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionUM
@@ -40,7 +43,8 @@ internal class WcSignTransactionModel @Inject constructor(
private val router: Router,
private val clipboardManager: ClipboardManager,
private val useCaseFactory: WcRequestUseCaseFactory,
- private val converter: WcCommonTransactionUMConverter,
+ private val signTypedDataUMConverter: WcSignTypedDataUMConverter,
+ private val signTransactionUMConverter: WcSignTransactionUMConverter,
) : Model(), WcCommonTransactionModel {
private val params = paramsContainer.require()
@@ -58,24 +62,44 @@ internal class WcSignTransactionModel @Inject constructor(
useCase.invoke()
.onEach { signState ->
if (signingIsDone(signState)) return@onEach
- val signTransactionUM = converter.convert(
- WcCommonTransactionUMConverter.Input(
- useCase = useCase,
- signState = signState,
- actions = WcTransactionActionsUM(
- onShowVerifiedAlert = ::showVerifiedAlert,
- onDismiss = { cancel(useCase) },
- onSign = useCase::sign,
- onCopy = { copyData(useCase.rawSdkRequest.request.params) },
- ),
- ),
- ) as? WcSignTransactionUM
+ val signTransactionUM = convertToUI(useCase, signState)
_uiState.emit(signTransactionUM)
}
.launchIn(this)
}
}
+ private fun convertToUI(
+ useCase: WcMessageSignUseCase,
+ signState: WcSignState,
+ ): WcSignTransactionUM? {
+ val actions = WcTransactionActionsUM(
+ onShowVerifiedAlert = ::showVerifiedAlert,
+ onDismiss = { cancel(useCase) },
+ onSign = useCase::sign,
+ onCopy = { copyData(useCase.rawSdkRequest.request.params) },
+ )
+ return when (useCase.method) {
+ is WcEthMethod.SignTypedData -> signTypedDataUMConverter.convert(
+ WcSignTypedDataUMConverter.Input(
+ context = useCase,
+ signState = signState,
+ signModel = signState.signModel,
+ actions = actions,
+ ),
+ )
+ is WcEthMethod.MessageSign, is WcSolanaMethod.SignMessage -> signTransactionUMConverter.convert(
+ WcSignTransactionUMConverter.Input(
+ context = useCase,
+ signState = signState,
+ signModel = signState.signModel,
+ actions = actions,
+ ),
+ )
+ else -> null
+ }
+ }
+
override fun dismiss() {
_uiState.value?.transaction?.onDismiss?.invoke() ?: router.pop()
}
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/routes/WcTransactionRoutes.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/routes/WcTransactionRoutes.kt
index 4c23abfde5..843e0e291d 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/routes/WcTransactionRoutes.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/routes/WcTransactionRoutes.kt
@@ -3,6 +3,7 @@ package com.tangem.features.walletconnect.transaction.routes
import androidx.compose.runtime.Immutable
import com.tangem.core.decompose.navigation.Route
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
+import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUMV2
import kotlinx.serialization.Serializable
@Serializable
@@ -27,8 +28,17 @@ internal sealed class WcTransactionRoutes : TangemBottomSheetConfigContent, Rout
data class Verified(val appName: String) : Type()
data object UnknownDomain : Type()
data object UnsafeDomain : Type()
- data class MaliciousInfo(val description: String?, val onClick: () -> Unit) : Type()
- data class UnknownError(val errorMessage: String?, val onDismiss: () -> Unit) : Type()
+ data class BlockAidErrorInfo(
+ val description: String?,
+ val onClick: () -> Unit,
+ val iconType: MessageBottomSheetUMV2.Icon.Type,
+ val iconBgType: MessageBottomSheetUMV2.Icon.BackgroundType,
+ ) : Type()
+ data class UnknownError(
+ val errorMessage: String?,
+ val onDismiss: () -> Unit,
+ val onRetry: () -> Unit,
+ ) : Type()
}
}
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/blockaid/TransactionCheckResultsItem.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/blockaid/TransactionCheckResultsItem.kt
index 0ff92d4802..2b7aca4340 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/blockaid/TransactionCheckResultsItem.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/blockaid/TransactionCheckResultsItem.kt
@@ -11,11 +11,12 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.extensions.TextReference
-import com.tangem.core.ui.extensions.resolveReference
+import com.tangem.core.ui.extensions.isNullOrEmpty
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.walletconnect.impl.R
+import com.tangem.features.walletconnect.transaction.entity.blockaid.BlockAidNotificationUM
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcEstimatedWalletChangeUM
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcEstimatedWalletChangesUM
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
@@ -36,15 +37,17 @@ internal fun TransactionCheckResultsItem(
if (item.isLoading) {
WcEstimatedWalletChangesLoadingItem()
} else {
- if (item.notificationText != null) {
- WcTransactionCheckErrorItem(item.notificationText.resolveReference())
+ if (item.notification != null) {
+ WcTransactionCheckErrorItem(item.notification)
}
if (item.estimatedWalletChanges != null) {
WcEstimatedWalletChangesItem(item.estimatedWalletChanges)
} else if (item.spendAllowance != null) {
WcSpendAllowanceItem(item.spendAllowance, onClickAllowToSpend)
+ } else if (!item.additionalNotification.isNullOrEmpty()) {
+ WcEstimatedWalletChangesNotificationItem(description = item.additionalNotification)
} else {
- WcEstimatedWalletChangesNotLoadedItem()
+ WcEstimatedWalletChangesNotificationItem()
}
}
}
@@ -70,7 +73,11 @@ private class TransactionCheckResultsItemProvider : PreviewParameterProvider {
override fun convert(value: Input): WcSendReceiveTransactionCheckResultsUM {
- val description = value.result.description
+ val description = value.result.description?.let { if (it.isNotEmpty()) TextReference.Str(it) else null }
+ val simulation = value.result.simulation
return WcSendReceiveTransactionCheckResultsUM(
isLoading = false,
- notificationText = when (value.result.validation) {
+ notification = when (value.result.validation) {
ValidationResult.SAFE, ValidationResult.FAILED_TO_VALIDATE -> null
- ValidationResult.UNSAFE -> if (!description.isNullOrEmpty()) TextReference.Str(description) else null
+ ValidationResult.UNSAFE -> BlockAidNotificationUM(
+ type = BlockAidNotificationUM.Type.ERROR,
+ title = TextReference.Res(R.string.wc_malicious_transaction),
+ text = description,
+ )
+ ValidationResult.WARNING -> BlockAidNotificationUM(
+ type = BlockAidNotificationUM.Type.WARNING,
+ title = TextReference.Res(R.string.wc_warning_transaction),
+ text = description,
+ )
},
- estimatedWalletChanges = (value.result.simulation as? SimulationResult.Success)?.data?.let { data ->
+ additionalNotification = (simulation as? SimulationResult.Success)?.data?.let { data ->
+ if (data is SimulationData.NoWalletChangesDetected) {
+ TextReference.Res(R.string.wc_no_wallet_changes_detected)
+ } else {
+ null
+ }
+ },
+ estimatedWalletChanges = (simulation as? SimulationResult.Success)?.data?.let { data ->
when (data) {
- is SimulationData.Approve -> null
+ is SimulationData.Approve, SimulationData.NoWalletChangesDetected -> null
is SimulationData.SendAndReceive -> {
val items: ImmutableList = (
data.send.map {
@@ -84,7 +102,7 @@ internal class WcSendAndReceiveBlockAidUiConverter @Inject constructor(
},
spendAllowance = (value.result.simulation as? SimulationResult.Success)?.data?.let { data ->
when (data) {
- is SimulationData.SendAndReceive -> null
+ is SimulationData.SendAndReceive, SimulationData.NoWalletChangesDetected -> null
is SimulationData.Approve -> value.approvedAmount?.let {
spendAllowanceUMConverter.convert(it)
}
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/blockaid/WcTransactionCheckErrorItem.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/blockaid/WcTransactionCheckErrorItem.kt
index a8431340b3..a5d01a0246 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/blockaid/WcTransactionCheckErrorItem.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/blockaid/WcTransactionCheckErrorItem.kt
@@ -11,26 +11,42 @@ import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.components.notifications.NotificationConfig
import com.tangem.core.ui.extensions.TextReference
-import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.walletconnect.impl.R
+import com.tangem.features.walletconnect.transaction.entity.blockaid.BlockAidNotificationUM
@Composable
-internal fun WcTransactionCheckErrorItem(notificationText: String, modifier: Modifier = Modifier) {
+internal fun WcTransactionCheckErrorItem(notification: BlockAidNotificationUM, modifier: Modifier = Modifier) {
Notification(
modifier = modifier
.fillMaxWidth(),
config = NotificationConfig(
- title = resourceReference(R.string.wc_malicious_transaction),
- subtitle = TextReference.Str(notificationText),
- iconResId = R.drawable.ic_alert_circle_24,
+ title = notification.title,
+ subtitle = TextReference.Str(notification.text?.resolveReference() ?: ""),
+ iconResId = when (notification.type) {
+ BlockAidNotificationUM.Type.ERROR -> R.drawable.ic_alert_circle_24
+ BlockAidNotificationUM.Type.WARNING -> R.drawable.ic_alert_triangle_20
+ },
),
- containerColor = TangemColorPalette.Amaranth.copy(alpha = 0.1f),
- titleColor = TangemTheme.colors.text.warning,
- subtitleColor = TangemTheme.colors.text.primary1,
- iconTint = TangemTheme.colors.icon.warning,
+ containerColor = when (notification.type) {
+ BlockAidNotificationUM.Type.ERROR -> TangemColorPalette.Amaranth.copy(alpha = 0.1f)
+ BlockAidNotificationUM.Type.WARNING -> TangemColorPalette.Dark1.copy(alpha = 0.1f)
+ },
+ titleColor = when (notification.type) {
+ BlockAidNotificationUM.Type.ERROR -> TangemTheme.colors.text.warning
+ BlockAidNotificationUM.Type.WARNING -> TangemTheme.colors.text.primary1
+ },
+ subtitleColor = when (notification.type) {
+ BlockAidNotificationUM.Type.ERROR -> TangemTheme.colors.text.primary1
+ BlockAidNotificationUM.Type.WARNING -> TangemTheme.colors.text.tertiary
+ },
+ iconTint = when (notification.type) {
+ BlockAidNotificationUM.Type.ERROR -> TangemTheme.colors.icon.warning
+ BlockAidNotificationUM.Type.WARNING -> TangemTheme.colors.icon.attention
+ },
)
}
@@ -43,7 +59,13 @@ private fun WcTransactionCheckErrorItemPreview() {
modifier = Modifier
.background(TangemTheme.colors.background.tertiary),
) {
- WcTransactionCheckErrorItem("The transaction approves erc20 tokens to a known malicious address")
+ WcTransactionCheckErrorItem(
+ BlockAidNotificationUM(
+ type = BlockAidNotificationUM.Type.ERROR,
+ title = TextReference.Res(R.string.wc_malicious_transaction),
+ text = TextReference.Str("The transaction approves erc20 tokens to a known malicious address"),
+ ),
+ )
}
}
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcAddressItem.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcAddressItem.kt
index f14eb7984b..35e9a28c76 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcAddressItem.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcAddressItem.kt
@@ -5,20 +5,23 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
+import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
+import com.tangem.core.ui.components.SpacerWMax
+import com.tangem.core.ui.components.atoms.text.EllipsisText
+import com.tangem.core.ui.components.atoms.text.TextEllipsis
import com.tangem.core.ui.components.tooltip.TangemTooltip
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.walletconnect.impl.R
-import com.tangem.features.walletconnect.transaction.entity.common.WcAddressUM
@Composable
-internal fun WcAddressItem(address: WcAddressUM, modifier: Modifier = Modifier) {
+internal fun WcAddressItem(address: String, modifier: Modifier = Modifier) {
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
+ var isTooltipEnabled by remember { mutableStateOf(false) }
Icon(
modifier = Modifier.size(TangemTheme.dimens.size24),
painter = painterResource(R.drawable.ic_user_square_24),
@@ -26,25 +29,26 @@ internal fun WcAddressItem(address: WcAddressUM, modifier: Modifier = Modifier)
tint = TangemTheme.colors.icon.accent,
)
Text(
- modifier = Modifier
- .padding(start = TangemTheme.dimens.spacing8)
- .weight(1f),
+ modifier = Modifier.padding(start = TangemTheme.dimens.spacing8),
text = stringResourceSafe(R.string.wc_common_address),
style = TangemTheme.typography.body1,
color = TangemTheme.colors.text.primary1,
+ maxLines = 1,
)
+ SpacerWMax()
TangemTooltip(
- modifier = Modifier
- .padding(start = TangemTheme.dimens.spacing16)
- .weight(1f),
- text = address.fullAddress,
+ modifier = Modifier.padding(start = TangemTheme.dimens.spacing16),
+ text = address,
+ enabled = isTooltipEnabled,
content = { contentModifier ->
- Text(
+ EllipsisText(
+ onTextLayout = { isTooltipEnabled = !it.hasVisualOverflow },
modifier = contentModifier,
- text = address.shortAddress,
+ text = address,
textAlign = TextAlign.End,
style = TangemTheme.typography.body1,
color = TangemTheme.colors.text.tertiary,
+ ellipsis = TextEllipsis.Middle,
)
},
)
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkItem.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkItem.kt
index fe95a18f69..bc1a75f3fa 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkItem.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkItem.kt
@@ -1,16 +1,21 @@
package com.tangem.features.walletconnect.transaction.ui.common
import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
+import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.style.TextOverflow
+import com.tangem.core.ui.components.tooltip.TangemTooltip
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.walletconnect.impl.R
@@ -22,39 +27,46 @@ internal fun WcNetworkItem(networkInfo: WcNetworkInfoUM, modifier: Modifier = Mo
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
) {
+ var isTooltipEnabled by remember { mutableStateOf(false) }
Icon(
modifier = Modifier.size(TangemTheme.dimens.size24),
painter = painterResource(R.drawable.ic_network_new_24),
contentDescription = null,
tint = TangemTheme.colors.icon.accent,
)
- Text(
- modifier = Modifier
- .padding(start = TangemTheme.dimens.spacing8)
- .weight(1f),
- text = stringResourceSafe(R.string.wc_common_network),
- style = TangemTheme.typography.body1,
- color = TangemTheme.colors.text.primary1,
- )
- Row(
- verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.End,
- modifier = Modifier.weight(1f),
- ) {
+ Row(modifier = Modifier.weight(1f), horizontalArrangement = Arrangement.SpaceBetween) {
Text(
- text = networkInfo.name,
+ modifier = Modifier.padding(start = TangemTheme.dimens.spacing8),
+ text = stringResourceSafe(R.string.wc_common_network),
style = TangemTheme.typography.body1,
- color = TangemTheme.colors.text.tertiary,
+ color = TangemTheme.colors.text.primary1,
+ maxLines = 1,
)
- Spacer(modifier = Modifier.width(TangemTheme.dimens.spacing6))
- Image(
- painter = painterResource(id = networkInfo.iconRes),
- contentDescription = null,
- contentScale = ContentScale.Crop,
- modifier = Modifier
- .clip(CircleShape)
- .size(TangemTheme.dimens.size20),
+ TangemTooltip(
+ modifier = Modifier.padding(start = TangemTheme.dimens.spacing16),
+ text = networkInfo.name,
+ enabled = isTooltipEnabled,
+ content = { contentModifier ->
+ Text(
+ modifier = contentModifier,
+ text = networkInfo.name,
+ style = TangemTheme.typography.body1,
+ color = TangemTheme.colors.text.tertiary,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ onTextLayout = { isTooltipEnabled = it.hasVisualOverflow },
+ )
+ },
)
}
+ Image(
+ painter = painterResource(id = networkInfo.iconRes),
+ contentDescription = null,
+ contentScale = ContentScale.Crop,
+ modifier = Modifier
+ .padding(start = TangemTheme.dimens.spacing6)
+ .clip(CircleShape)
+ .size(TangemTheme.dimens.size20),
+ )
}
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcSendTransactionItems.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcSendTransactionItems.kt
index 6b703bf94d..fe0f4cfc06 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcSendTransactionItems.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcSendTransactionItems.kt
@@ -15,23 +15,26 @@ import com.tangem.core.ui.components.divider.DividerWithPadding
import com.tangem.core.ui.extensions.clickableSingle
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.send.v2.api.FeeSelectorBlockComponent
-import com.tangem.features.walletconnect.transaction.entity.common.WcAddressUM
+import com.tangem.features.send.v2.api.entity.FeeSelectorUM
import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionFeeState
+@Suppress("LongParameterList")
@Composable
internal fun WcSendTransactionItems(
walletName: String?,
networkInfo: WcNetworkInfoUM,
feeState: WcTransactionFeeState,
feeSelectorBlockComponent: FeeSelectorBlockComponent?,
- address: WcAddressUM?,
+ feeSelectorUM: FeeSelectorUM,
+ address: String?,
modifier: Modifier = Modifier,
) {
- val onFeeBlockClicked = remember(feeState) {
- when (feeState) {
- WcTransactionFeeState.None -> null
- is WcTransactionFeeState.Success -> feeState.onClick
+ val onFeeBlockClicked = remember(feeState, feeSelectorUM) {
+ if (feeState is WcTransactionFeeState.Success && feeSelectorUM is FeeSelectorUM.Content) {
+ feeState.onClick
+ } else {
+ null
}
}
Column(
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcTransactionRequestButtons.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcTransactionRequestButtons.kt
index 9d8ec8d0fb..ed0217aee9 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcTransactionRequestButtons.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcTransactionRequestButtons.kt
@@ -20,6 +20,7 @@ internal fun WcTransactionRequestButtons(
onDismiss: () -> Unit,
onClickActiveButton: () -> Unit,
modifier: Modifier = Modifier,
+ enabled: Boolean = true,
) {
Row(modifier = modifier, horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) {
SecondaryButton(
@@ -37,6 +38,7 @@ internal fun WcTransactionRequestButtons(
onClick = onClickActiveButton,
iconResId = R.drawable.ic_tangem_24,
showProgress = isLoading,
+ enabled = enabled,
)
}
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcWalletItem.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcWalletItem.kt
index 18babacc67..3a416412ee 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcWalletItem.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcWalletItem.kt
@@ -5,11 +5,13 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
+import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import com.tangem.core.ui.components.SpacerWMax
+import com.tangem.core.ui.components.tooltip.TangemTooltip
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.walletconnect.impl.R
@@ -17,6 +19,7 @@ import com.tangem.features.walletconnect.impl.R
@Composable
internal fun WcWalletItem(walletName: String, modifier: Modifier = Modifier) {
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
+ var isTooltipEnabled by remember { mutableStateOf(false) }
Icon(
modifier = Modifier.size(TangemTheme.dimens.size24),
painter = painterResource(R.drawable.ic_wallet_new_24),
@@ -24,21 +27,28 @@ internal fun WcWalletItem(walletName: String, modifier: Modifier = Modifier) {
tint = TangemTheme.colors.icon.accent,
)
Text(
- modifier = Modifier
- .padding(start = TangemTheme.dimens.spacing8)
- .weight(1f),
+ modifier = Modifier.padding(start = TangemTheme.dimens.spacing8),
text = stringResourceSafe(R.string.manage_tokens_network_selector_wallet),
style = TangemTheme.typography.body1,
color = TangemTheme.colors.text.primary1,
+ maxLines = 1,
)
- Text(
- modifier = Modifier
- .padding(start = TangemTheme.dimens.spacing16)
- .weight(1f),
+ SpacerWMax()
+ TangemTooltip(
+ modifier = Modifier.padding(start = TangemTheme.dimens.spacing16),
text = walletName,
- textAlign = TextAlign.End,
- style = TangemTheme.typography.body1,
- color = TangemTheme.colors.text.tertiary,
+ enabled = isTooltipEnabled,
+ content = { contentModifier ->
+ Text(
+ modifier = contentModifier,
+ text = walletName,
+ style = TangemTheme.typography.body1,
+ color = TangemTheme.colors.text.tertiary,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ onTextLayout = { isTooltipEnabled = it.hasVisualOverflow },
+ )
+ },
)
}
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/send/WcSendTransactionModalBottomSheet.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/send/WcSendTransactionModalBottomSheet.kt
index 08a5ea45b0..0a0a1f1eac 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/send/WcSendTransactionModalBottomSheet.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/send/WcSendTransactionModalBottomSheet.kt
@@ -4,7 +4,9 @@ import android.content.res.Configuration
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@@ -14,25 +16,29 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import androidx.compose.ui.unit.dp
+import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetWithFooter
import com.tangem.core.ui.components.divider.DividerWithPadding
+import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.send.v2.api.FeeSelectorBlockComponent
+import com.tangem.features.send.v2.api.entity.FeeSelectorUM
import com.tangem.features.walletconnect.connections.entity.VerifiedDAppState
import com.tangem.features.walletconnect.connections.ui.WcAppInfoItem
import com.tangem.features.walletconnect.impl.R
import com.tangem.features.walletconnect.transaction.components.PreviewFeeSelectorBlockComponent
+import com.tangem.features.walletconnect.transaction.entity.blockaid.BlockAidNotificationUM
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcEstimatedWalletChangeUM
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcEstimatedWalletChangesUM
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
-import com.tangem.features.walletconnect.transaction.entity.common.WcAddressUM
import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionAppInfoContentUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionFeeState
@@ -49,6 +55,7 @@ import kotlinx.collections.immutable.persistentListOf
internal fun WcSendTransactionModalBottomSheet(
state: WcSendTransactionItemUM,
feeSelectorBlockComponent: FeeSelectorBlockComponent?,
+ feeSelectorUM: FeeSelectorUM,
onClickTransactionRequest: () -> Unit,
onBack: () -> Unit,
onDismiss: () -> Unit,
@@ -101,14 +108,23 @@ internal fun WcSendTransactionModalBottomSheet(
if (state.estimatedWalletChanges != null) {
TransactionCheckResultsItem(state.estimatedWalletChanges, onClickAllowToSpend)
}
- Spacer(Modifier.height(16.dp))
WcSendTransactionItems(
+ modifier = Modifier.padding(top = 16.dp),
walletName = state.walletName,
networkInfo = state.networkInfo,
feeState = state.feeState,
feeSelectorBlockComponent = feeSelectorBlockComponent,
+ feeSelectorUM = feeSelectorUM,
address = state.address,
)
+ if (state.feeErrorNotification != null) {
+ Notification(
+ modifier = Modifier.padding(top = 14.dp),
+ config = state.feeErrorNotification.config,
+ iconTint = TangemTheme.colors.icon.warning,
+ containerColor = TangemTheme.colors.button.disabled,
+ )
+ }
}
}
},
@@ -119,6 +135,7 @@ internal fun WcSendTransactionModalBottomSheet(
onClickActiveButton = state.onSend,
activeButtonText = resourceReference(R.string.common_send),
isLoading = state.isLoading,
+ enabled = state.sendEnabled,
)
},
)
@@ -155,6 +172,7 @@ private fun WcSendTransactionBottomSheetPreview(
onBack = {},
onDismiss = {},
onClickAllowToSpend = {},
+ feeSelectorUM = FeeSelectorUM.Loading,
)
},
)
@@ -173,8 +191,10 @@ private class WcSendTransactionStateProvider : CollectionPreviewParameterProvide
appSubtitle = "react-app.walletconnect.com",
),
estimatedWalletChanges = WcSendReceiveTransactionCheckResultsUM(
- notificationText = TextReference.Str(
- "The transaction approves erc20 tokens to a known malicious address",
+ notification = BlockAidNotificationUM(
+ type = BlockAidNotificationUM.Type.ERROR,
+ title = TextReference.Res(R.string.wc_malicious_transaction),
+ text = TextReference.Str("The transaction approves erc20 tokens to a known malicious address"),
),
estimatedWalletChanges = WcEstimatedWalletChangesUM(
items = persistentListOf(
@@ -194,10 +214,12 @@ private class WcSendTransactionStateProvider : CollectionPreviewParameterProvide
),
isLoading = false,
),
- walletName = "Tangem 2.0",
- networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
- feeState = WcTransactionFeeState.Success(null, {}),
+ walletName = "Tangem 2.0 Tangem 2.0 Tangem 2",
+ networkInfo = WcNetworkInfoUM(name = "Optimistic Ethereum Network", iconRes = R.drawable.img_eth_22),
+ feeState = WcTransactionFeeState.Success(dAppFee = null, onClick = {}),
address = null,
+ sendEnabled = true,
+ feeErrorNotification = null,
),
WcSendTransactionItemUM(
onDismiss = {},
@@ -209,8 +231,10 @@ private class WcSendTransactionStateProvider : CollectionPreviewParameterProvide
appSubtitle = "react-app.walletconnect.com",
),
estimatedWalletChanges = WcSendReceiveTransactionCheckResultsUM(
- notificationText = TextReference.Str(
- "The transaction approves erc20 tokens to a known malicious address",
+ notification = BlockAidNotificationUM(
+ type = BlockAidNotificationUM.Type.ERROR,
+ title = TextReference.Res(R.string.wc_malicious_transaction),
+ text = TextReference.Str("The transaction approves erc20 tokens to a known malicious address"),
),
estimatedWalletChanges = WcEstimatedWalletChangesUM(
items = persistentListOf(
@@ -231,8 +255,13 @@ private class WcSendTransactionStateProvider : CollectionPreviewParameterProvide
),
walletName = "Tangem 2.0",
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
- feeState = WcTransactionFeeState.Success(null, {}),
- address = WcAddressUM("0xdac17f958d2ee523a2206206994597c13d831ec7", "0x345FF...34FA"),
+ feeState = WcTransactionFeeState.Success(dAppFee = null, onClick = {}),
+ address = "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ sendEnabled = true,
+ feeErrorNotification = NotificationUM.Info(
+ title = stringReference("Insufficient Ethereum"),
+ subtitle = stringReference("Top up your balance to cover the network fee"),
+ ),
),
WcSendTransactionItemUM(
onDismiss = {},
@@ -244,8 +273,10 @@ private class WcSendTransactionStateProvider : CollectionPreviewParameterProvide
appSubtitle = "react-app.walletconnect.com",
),
estimatedWalletChanges = WcSendReceiveTransactionCheckResultsUM(
- notificationText = TextReference.Str(
- "The transaction approves erc20 tokens to a known malicious address",
+ notification = BlockAidNotificationUM(
+ type = BlockAidNotificationUM.Type.ERROR,
+ title = TextReference.Res(R.string.wc_malicious_transaction),
+ text = TextReference.Str("The transaction approves erc20 tokens to a known malicious address"),
),
estimatedWalletChanges = WcEstimatedWalletChangesUM(
items = persistentListOf(
@@ -268,6 +299,11 @@ private class WcSendTransactionStateProvider : CollectionPreviewParameterProvide
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
feeState = WcTransactionFeeState.None,
address = null,
+ sendEnabled = false,
+ feeErrorNotification = NotificationUM.Info(
+ title = stringReference("Insufficient Ethereum"),
+ subtitle = stringReference("Top up your balance to cover the network fee"),
+ ),
),
),
)
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheetContent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheetContent.kt
index b6aba3ab28..86e7fad3f4 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheetContent.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheetContent.kt
@@ -28,7 +28,6 @@ import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.walletconnect.connections.entity.VerifiedDAppState
import com.tangem.features.walletconnect.connections.ui.WcAppInfoItem
import com.tangem.features.walletconnect.impl.R
-import com.tangem.features.walletconnect.transaction.entity.common.WcAddressUM
import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionAppInfoContentUM
import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionItemUM
@@ -196,7 +195,7 @@ private class WcSignTransactionStateProvider : CollectionPreviewParameterProvide
),
walletName = null,
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
- address = WcAddressUM("0xdac17f958d2ee523a2206206994597c13d831ec7", "0x345FF...34FA"),
+ address = "0xdac17f958d2ee523a2206206994597c13d831ec7",
),
),
)
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/utils/WcNotificationsFactory.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/utils/WcNotificationsFactory.kt
new file mode 100644
index 0000000000..f36b09dc1c
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/utils/WcNotificationsFactory.kt
@@ -0,0 +1,65 @@
+package com.tangem.features.walletconnect.utils
+
+import com.tangem.blockchain.common.transaction.TransactionFee
+import com.tangem.common.ui.notifications.NotificationUM
+import com.tangem.core.ui.components.notifications.NotificationConfig
+import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.core.ui.extensions.stringReference
+import com.tangem.domain.models.currency.CryptoCurrencyStatus
+import com.tangem.features.send.v2.api.entity.FeeSelectorUM
+import com.tangem.features.send.v2.api.subcomponents.feeSelector.utils.FeeCalculationUtils
+import com.tangem.features.walletconnect.impl.R
+import javax.inject.Inject
+
+internal class WcNotificationsFactory @Inject constructor() {
+
+ fun createFeeNotifications(
+ cryptoCurrencyStatus: CryptoCurrencyStatus,
+ feeSelectorUM: FeeSelectorUM?,
+ onFeeReload: () -> Unit,
+ ): NotificationUM.Info? {
+ return when (feeSelectorUM) {
+ is FeeSelectorUM.Content -> createFeeExceedsBalance(cryptoCurrencyStatus, feeSelectorUM)
+ is FeeSelectorUM.Error -> createFeeErrorNotification(onFeeReload)
+ FeeSelectorUM.Loading, null -> null
+ }
+ }
+
+ private fun createFeeExceedsBalance(
+ cryptoCurrencyStatus: CryptoCurrencyStatus,
+ feeSelectorUM: FeeSelectorUM?,
+ ): NotificationUM.Info? {
+ // TODO: [REDACTED_TASK_KEY] localization
+ return NotificationUM.Info(
+ title = stringReference("Insufficient ${cryptoCurrencyStatus.currency.name}"),
+ subtitle = stringReference("Top up your balance to cover the network fee"),
+ ).takeIf { isFeeExceedsBalance(cryptoCurrencyStatus = cryptoCurrencyStatus, feeSelectorUM = feeSelectorUM) }
+ }
+
+ private fun createFeeErrorNotification(onFeeReload: () -> Unit): NotificationUM.Info {
+ return NotificationUM.Info(
+ title = resourceReference(R.string.send_fee_unreachable_error_title),
+ subtitle = resourceReference(R.string.send_fee_unreachable_error_text),
+ buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
+ text = resourceReference(R.string.warning_button_refresh),
+ onClick = onFeeReload,
+ ),
+ )
+ }
+
+ private fun isFeeExceedsBalance(
+ cryptoCurrencyStatus: CryptoCurrencyStatus,
+ feeSelectorUM: FeeSelectorUM?,
+ ): Boolean {
+ val feeSelectorContent = feeSelectorUM as? FeeSelectorUM.Content ?: return false
+ val lowestFee = when (val fees = feeSelectorContent.fees) {
+ is TransactionFee.Choosable -> fees.minimum
+ is TransactionFee.Single -> fees.normal
+ }
+
+ return FeeCalculationUtils.checkExceedBalance(
+ feeBalance = cryptoCurrencyStatus.value.amount,
+ feeAmount = lowestFee.amount.value,
+ )
+ }
+}
\ No newline at end of file