Updated on 2026-08-14
This commit is contained in:
parent
16156c559a
commit
bbd0c7927d
9 changed files with 133 additions and 32 deletions
|
|
@ -16,13 +16,16 @@ dependencies {
|
|||
implementation(projects.features.walletconnect.api)
|
||||
implementation(projects.features.sendV2.api)
|
||||
|
||||
/** Core */
|
||||
implementation(projects.core.configToggles)
|
||||
implementation(projects.core.decompose)
|
||||
implementation(projects.core.ui)
|
||||
/** Common */
|
||||
implementation(projects.common.routing)
|
||||
implementation(projects.common.ui)
|
||||
|
||||
/** Core */
|
||||
implementation(projects.core.analytics)
|
||||
implementation(projects.core.configToggles)
|
||||
implementation(projects.core.decompose)
|
||||
implementation(projects.core.navigation)
|
||||
implementation(projects.core.ui)
|
||||
|
||||
/** Domain models */
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
|
|
|
|||
|
|
@ -11,4 +11,5 @@ internal data class WcSpendAllowanceUM(
|
|||
val tokenSymbol: String,
|
||||
val tokenImageUrl: String?,
|
||||
val networkIconRes: Int?,
|
||||
val onLearnMoreClicked: () -> Unit,
|
||||
) : TangemBottomSheetConfigContent
|
||||
|
|
@ -16,6 +16,7 @@ import com.tangem.core.decompose.model.Model
|
|||
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.navigation.url.UrlOpener
|
||||
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
|
||||
|
|
@ -55,6 +56,7 @@ import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransacti
|
|||
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.SupportedLanguages
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -74,11 +76,11 @@ internal class WcSendTransactionModel @Inject constructor(
|
|||
private val clipboardManager: ClipboardManager,
|
||||
private val useCaseFactory: WcRequestUseCaseFactory,
|
||||
private val converter: WcSendTransactionUMConverter,
|
||||
private val blockAidUiConverter: WcSendAndReceiveBlockAidUiConverter,
|
||||
private val getFeeUseCase: GetFeeUseCase,
|
||||
private val getNetworkCoinUseCase: GetNetworkCoinStatusUseCase,
|
||||
private val notificationsFactory: WcNotificationsFactory,
|
||||
private val analytics: AnalyticsEventHandler,
|
||||
private val urlOpener: UrlOpener,
|
||||
) : Model(), WcCommonTransactionModel, FeeSelectorModelCallback {
|
||||
|
||||
private val params = paramsContainer.require<WcTransactionModelParams>()
|
||||
|
|
@ -94,6 +96,7 @@ internal class WcSendTransactionModel @Inject constructor(
|
|||
private var signState: WcSignState<*> by Delegates.notNull()
|
||||
private var wcApproval: WcApproval? = null
|
||||
private var sign: () -> Unit = {}
|
||||
private val blockAidUiConverter = WcSendAndReceiveBlockAidUiConverter()
|
||||
private val feeReloadState = MutableStateFlow(false)
|
||||
private val signatureReceivedAnalyticsSendState = MutableStateFlow(false)
|
||||
private val securityStatusState =
|
||||
|
|
@ -243,8 +246,9 @@ internal class WcSendTransactionModel @Inject constructor(
|
|||
val blockAidState = when (securityCheck) {
|
||||
is Lce.Content -> blockAidUiConverter.convert(
|
||||
WcSendAndReceiveBlockAidUiConverter.Input(
|
||||
securityCheck.content.result,
|
||||
if (isApproval) wcApproval?.getAmount() else null,
|
||||
result = securityCheck.content.result,
|
||||
approvedAmount = if (isApproval) wcApproval?.getAmount() else null,
|
||||
onApproveLearnMoreClick = ::onApproveLearnMoreClick,
|
||||
),
|
||||
)
|
||||
is Lce.Error -> WcSendReceiveTransactionCheckResultsUM(isLoading = false)
|
||||
|
|
@ -291,6 +295,15 @@ internal class WcSendTransactionModel @Inject constructor(
|
|||
stackNavigation.pop()
|
||||
}
|
||||
|
||||
private fun onApproveLearnMoreClick() {
|
||||
val code = SupportedLanguages.getCurrentSupportedLanguageCode()
|
||||
.takeIf { it == SupportedLanguages.RUSSIAN }
|
||||
?: SupportedLanguages.ENGLISH
|
||||
|
||||
val url = "https://tangem.com/$code/blog/post/give-revoke-permission/"
|
||||
urlOpener.openUrl(url)
|
||||
}
|
||||
|
||||
private fun isMultipleSignRequired(useCase: WcSignUseCase<*>): Boolean {
|
||||
return if (useCase is SignRequirements) {
|
||||
useCase.isMultipleSignRequired()
|
||||
|
|
|
|||
|
|
@ -255,6 +255,7 @@ private class WcCustomAllowanceStateProvider : CollectionPreviewParameterProvide
|
|||
amountValue = BigDecimal("100"),
|
||||
tokenSymbol = "ETH",
|
||||
isUnlimited = false,
|
||||
onLearnMoreClicked = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -3,25 +3,29 @@ package com.tangem.features.walletconnect.transaction.ui.blockaid
|
|||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.LinkAnnotation
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.withLink
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
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.isNullOrEmpty
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.*
|
||||
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.approve.WcSpendAllowanceUM
|
||||
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.ui.approve.WcSpendAllowanceItem
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Composable
|
||||
internal fun TransactionCheckResultsItem(
|
||||
|
|
@ -29,11 +33,7 @@ internal fun TransactionCheckResultsItem(
|
|||
onClickAllowToSpend: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxWidth(),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Column(modifier = modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
if (item.isLoading) {
|
||||
WcEstimatedWalletChangesLoadingItem()
|
||||
} else {
|
||||
|
|
@ -44,6 +44,10 @@ internal fun TransactionCheckResultsItem(
|
|||
WcEstimatedWalletChangesItem(item.estimatedWalletChanges)
|
||||
} else if (item.spendAllowance != null) {
|
||||
WcSpendAllowanceItem(item.spendAllowance, onClickAllowToSpend)
|
||||
ApproveDescription(
|
||||
modifier = Modifier.padding(bottom = 6.dp, start = 12.dp, end = 12.dp),
|
||||
onLearnMoreClick = item.spendAllowance.onLearnMoreClicked,
|
||||
)
|
||||
} else if (!item.additionalNotification.isNullOrEmpty()) {
|
||||
WcEstimatedWalletChangesNotificationItem(description = item.additionalNotification)
|
||||
} else {
|
||||
|
|
@ -53,6 +57,29 @@ internal fun TransactionCheckResultsItem(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ApproveDescription(modifier: Modifier = Modifier, onLearnMoreClick: () -> Unit) {
|
||||
val linkText = stringResourceSafe(R.string.common_learn_more)
|
||||
val fullString = stringResourceSafe(R.string.wc_approve_description)
|
||||
val defaultColor = TangemTheme.colors.text.tertiary
|
||||
val linkColor = TangemTheme.colors.text.accent
|
||||
Text(
|
||||
modifier = modifier,
|
||||
style = TangemTheme.typography.caption2,
|
||||
text = buildAnnotatedString {
|
||||
appendColored(fullString, defaultColor)
|
||||
appendSpace()
|
||||
withLink(
|
||||
link = LinkAnnotation.Clickable(
|
||||
tag = "WC_APPROVE_LEARN_MORE_TAG",
|
||||
linkInteractionListener = { onLearnMoreClick() },
|
||||
),
|
||||
block = { appendColored(text = linkText, color = linkColor) },
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO)
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
|
|
@ -95,5 +122,22 @@ private class TransactionCheckResultsItemProvider : PreviewParameterProvider<WcS
|
|||
),
|
||||
),
|
||||
),
|
||||
WcSendReceiveTransactionCheckResultsUM(
|
||||
isLoading = false,
|
||||
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"),
|
||||
),
|
||||
spendAllowance = WcSpendAllowanceUM(
|
||||
amountValue = BigDecimal.ZERO,
|
||||
isUnlimited = false,
|
||||
amountText = stringReference("0.00 WPOL"),
|
||||
tokenSymbol = "",
|
||||
tokenImageUrl = "",
|
||||
networkIconRes = 0,
|
||||
onLearnMoreClicked = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -6,9 +6,8 @@ import com.tangem.core.ui.format.bigdecimal.crypto
|
|||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcEstimatedWalletChangeUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class WcEstimatedWalletChangeUMConverter @Inject constructor() :
|
||||
internal class WcEstimatedWalletChangeUMConverter :
|
||||
Converter<WcEstimatedWalletChangeUMConverter.Input, WcEstimatedWalletChangeUM> {
|
||||
|
||||
override fun convert(value: Input): WcEstimatedWalletChangeUM {
|
||||
|
|
|
|||
|
|
@ -20,15 +20,16 @@ import com.tangem.utils.converter.Converter
|
|||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import java.math.BigDecimal
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val DECIMALS_AMOUNT = 2
|
||||
|
||||
@Suppress("CyclomaticComplexMethod", "LongMethod")
|
||||
internal class WcSendAndReceiveBlockAidUiConverter @Inject constructor(
|
||||
private val estimatedWalletChangeUMConverter: WcEstimatedWalletChangeUMConverter,
|
||||
private val spendAllowanceUMConverter: WcSpendAllowanceUMConverter,
|
||||
) : Converter<WcSendAndReceiveBlockAidUiConverter.Input, WcSendReceiveTransactionCheckResultsUM> {
|
||||
internal class WcSendAndReceiveBlockAidUiConverter :
|
||||
Converter<WcSendAndReceiveBlockAidUiConverter.Input, WcSendReceiveTransactionCheckResultsUM> {
|
||||
|
||||
private val estimatedWalletChangeUMConverter = WcEstimatedWalletChangeUMConverter()
|
||||
private val spendAllowanceUMConverter = WcSpendAllowanceUMConverter()
|
||||
|
||||
override fun convert(value: Input): WcSendReceiveTransactionCheckResultsUM {
|
||||
val description = value.result.description?.let { if (it.isNotEmpty()) TextReference.Str(it) else null }
|
||||
val simulation = value.result.simulation
|
||||
|
|
@ -118,7 +119,12 @@ internal class WcSendAndReceiveBlockAidUiConverter @Inject constructor(
|
|||
when (data) {
|
||||
is SimulationData.SendAndReceive, SimulationData.NoWalletChangesDetected -> null
|
||||
is SimulationData.Approve -> value.approvedAmount?.let {
|
||||
spendAllowanceUMConverter.convert(it)
|
||||
spendAllowanceUMConverter.convert(
|
||||
WcSpendAllowanceUMConverter.Input(
|
||||
approvedAmount = it,
|
||||
onLearnMoreClick = value.onApproveLearnMoreClick,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -128,6 +134,7 @@ internal class WcSendAndReceiveBlockAidUiConverter @Inject constructor(
|
|||
data class Input(
|
||||
val result: CheckTransactionResult,
|
||||
val approvedAmount: WcApprovedAmount?,
|
||||
val onApproveLearnMoreClick: () -> Unit,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,24 +6,26 @@ import com.tangem.domain.walletconnect.model.WcApprovedAmount
|
|||
import com.tangem.features.walletconnect.impl.R
|
||||
import com.tangem.features.walletconnect.transaction.entity.approve.WcSpendAllowanceUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class WcSpendAllowanceUMConverter @Inject constructor() : Converter<WcApprovedAmount, WcSpendAllowanceUM> {
|
||||
internal class WcSpendAllowanceUMConverter : Converter<WcSpendAllowanceUMConverter.Input, WcSpendAllowanceUM> {
|
||||
|
||||
override fun convert(value: WcApprovedAmount): WcSpendAllowanceUM {
|
||||
val amount = value.amount?.value ?: 0.0.toBigDecimal()
|
||||
val isUnlimited = value.amount?.value == null
|
||||
override fun convert(value: Input): WcSpendAllowanceUM {
|
||||
val amount = value.approvedAmount.amount?.value ?: 0.0.toBigDecimal()
|
||||
val isUnlimited = value.approvedAmount.amount?.value == null
|
||||
return WcSpendAllowanceUM(
|
||||
amountValue = amount,
|
||||
amountText = if (value.amount?.value == null) {
|
||||
amountText = if (value.approvedAmount.amount?.value == null) {
|
||||
TextReference.Res(R.string.wc_common_unlimited)
|
||||
} else {
|
||||
TextReference.Str(amount.amountText())
|
||||
},
|
||||
isUnlimited = isUnlimited,
|
||||
tokenSymbol = value.amount?.currencySymbol ?: "",
|
||||
tokenImageUrl = value.logoUrl,
|
||||
networkIconRes = value.chainId?.toString()?.let { getActiveIconRes(it) },
|
||||
tokenSymbol = value.approvedAmount.amount?.currencySymbol ?: "",
|
||||
tokenImageUrl = value.approvedAmount.logoUrl,
|
||||
networkIconRes = value.approvedAmount.chainId?.toString()?.let { getActiveIconRes(it) },
|
||||
onLearnMoreClicked = value.onLearnMoreClick,
|
||||
)
|
||||
}
|
||||
|
||||
data class Input(val approvedAmount: WcApprovedAmount, val onLearnMoreClick: () -> Unit)
|
||||
}
|
||||
|
|
@ -37,6 +37,7 @@ 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.approve.WcSpendAllowanceUM
|
||||
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
|
||||
|
|
@ -51,6 +52,7 @@ import com.tangem.features.walletconnect.transaction.ui.common.WcSmallTitleItem
|
|||
import com.tangem.features.walletconnect.transaction.ui.common.WcTransactionRequestButtons
|
||||
import com.tangem.features.walletconnect.transaction.ui.common.WcTransactionRequestItem
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Suppress("LongParameterList", "LongMethod")
|
||||
@Composable
|
||||
|
|
@ -316,5 +318,34 @@ private class WcSendTransactionStateProvider : CollectionPreviewParameterProvide
|
|||
),
|
||||
transactionValidationResult = ValidationResult.SAFE,
|
||||
),
|
||||
WcSendTransactionItemUM(
|
||||
onDismiss = {},
|
||||
onSend = {},
|
||||
appInfo = WcTransactionAppInfoContentUM(
|
||||
appName = "React App",
|
||||
appIcon = "",
|
||||
verifiedState = VerifiedDAppState.Verified {},
|
||||
appSubtitle = "react-app.walletconnect.com",
|
||||
),
|
||||
estimatedWalletChanges = WcSendReceiveTransactionCheckResultsUM(
|
||||
isLoading = false,
|
||||
spendAllowance = WcSpendAllowanceUM(
|
||||
amountValue = BigDecimal.ZERO,
|
||||
isUnlimited = false,
|
||||
amountText = stringReference("0.00 WPOL"),
|
||||
tokenSymbol = "",
|
||||
tokenImageUrl = "",
|
||||
networkIconRes = 0,
|
||||
onLearnMoreClicked = {},
|
||||
),
|
||||
),
|
||||
walletName = "Tangem 2.0",
|
||||
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
|
||||
feeState = WcTransactionFeeState.None,
|
||||
address = "0xdac17f958d2ee523a2206206994597c13d831ec7",
|
||||
sendEnabled = true,
|
||||
feeErrorNotification = null,
|
||||
transactionValidationResult = ValidationResult.SAFE,
|
||||
),
|
||||
),
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue