diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 02d8bd7799..81f172e609 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -1299,6 +1299,7 @@
Will not be able to
Would like to
Connection request
+ Transaction request
Connections
Disconnect all
Text about discnected all dApps
@@ -1311,6 +1312,12 @@
This domain is flagged as unsafe by multiple security providers. Leave immediately to protect your assets
Known security risk
Wallet connect
+ Request from
+ Sign
+ Copy data
+ Transaction request
+ Signature Type
+ Contents
Discard
You have an interrupted backup. Do you want to resume?
Yes, resume
diff --git a/core/ui/src/main/res/drawable/ic_doc_new_24.xml b/core/ui/src/main/res/drawable/ic_doc_new_24.xml
new file mode 100644
index 0000000000..9f506aaa9d
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_doc_new_24.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/di/WalletConnectModelModule.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/di/WalletConnectModelModule.kt
index 00039ca420..a9f3afb61d 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/di/WalletConnectModelModule.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/di/WalletConnectModelModule.kt
@@ -5,6 +5,7 @@ import com.tangem.core.decompose.model.Model
import com.tangem.features.walletconnect.connections.model.WcAppInfoModel
import com.tangem.features.walletconnect.connections.model.WcConnectedAppInfoModel
import com.tangem.features.walletconnect.connections.model.WcConnectionsModel
+import com.tangem.features.walletconnect.transaction.model.WcSignTransactionModel
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
@@ -29,4 +30,9 @@ internal interface WalletConnectModelModule {
@IntoMap
@ClassKey(WcConnectedAppInfoModel::class)
fun bindWcConnectedAppInfoModel(model: WcConnectedAppInfoModel): Model
+
+ @Binds
+ @IntoMap
+ @ClassKey(WcSignTransactionModel::class)
+ fun bindWcSignTransactionModel(model: WcSignTransactionModel): Model
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionComponent.kt
new file mode 100644
index 0000000000..9ec9f43b8f
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/components/WcSignTransactionComponent.kt
@@ -0,0 +1,37 @@
+package com.tangem.features.walletconnect.transaction.components
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.tangem.core.decompose.context.AppComponentContext
+import com.tangem.core.decompose.model.getOrCreateModel
+import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
+import com.tangem.core.ui.decompose.ComposableContentComponent
+import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
+import com.tangem.features.walletconnect.transaction.model.WcSignTransactionModel
+import com.tangem.features.walletconnect.transaction.ui.sign.WcSignTransactionModalBottomSheet
+
+internal class WcSignTransactionComponent(
+ appComponentContext: AppComponentContext,
+ params: Params,
+) : AppComponentContext by appComponentContext, ComposableContentComponent {
+
+ private val model: WcSignTransactionModel = getOrCreateModel(params)
+
+ @Composable
+ override fun Content(modifier: Modifier) {
+ val content by model.uiState.collectAsStateWithLifecycle()
+ content?.let {
+ WcSignTransactionModalBottomSheet(
+ config = TangemBottomSheetConfig(
+ isShown = true,
+ onDismissRequest = it.actions.onDismiss,
+ content = it,
+ ),
+ )
+ }
+ }
+
+ data class Params(val rawRequest: WcSdkSessionRequest)
+}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/WcSignTransactionUM.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/WcSignTransactionUM.kt
new file mode 100644
index 0000000000..3f796ce6b1
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/entity/WcSignTransactionUM.kt
@@ -0,0 +1,60 @@
+package com.tangem.features.walletconnect.transaction.entity
+
+import androidx.annotation.DrawableRes
+import androidx.compose.runtime.Immutable
+import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
+import com.tangem.core.ui.extensions.TextReference
+import kotlinx.collections.immutable.ImmutableList
+
+@Immutable
+internal data class WcSignTransactionUM(
+ @DrawableRes val startIconRes: Int,
+ @DrawableRes val endIconRes: Int,
+ @DrawableRes val transactionIconRes: Int,
+ val actions: WcTransactionActionsUM,
+ val state: State = State.TRANSACTION,
+ val transaction: WcTransactionUM,
+ val transactionRequestInfo: WcTransactionRequestInfoUM,
+) : TangemBottomSheetConfigContent {
+
+ enum class State {
+ TRANSACTION, TRANSACTION_REQUEST_INFO
+ }
+}
+
+@Immutable
+internal data class WcTransactionUM(
+ val appName: String,
+ val appIcon: String,
+ val isVerified: Boolean,
+ val appSubtitle: String,
+ val walletName: String,
+ val networkInfo: WcNetworkInfoUM,
+ val isLoading: Boolean = false,
+)
+
+@Immutable
+internal data class WcTransactionRequestInfoUM(
+ val info: ImmutableList,
+)
+
+@Immutable
+internal data class WcTransactionRequestInfoItemUM(
+ val title: TextReference,
+ val description: String,
+)
+
+@Immutable
+internal data class WcTransactionActionsUM(
+ val transactionRequestOnClick: () -> Unit,
+ val onDismiss: () -> Unit,
+ val onSign: () -> Unit,
+ val onBack: () -> Unit,
+ val onCopy: () -> Unit,
+)
+
+@Immutable
+internal data class WcNetworkInfoUM(
+ val name: String,
+ @DrawableRes val iconRes: Int,
+)
\ No newline at end of file
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
new file mode 100644
index 0000000000..9a8eabf961
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt
@@ -0,0 +1,86 @@
+package com.tangem.features.walletconnect.transaction.model
+
+import androidx.compose.runtime.Stable
+import com.tangem.core.decompose.di.ModelScoped
+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.ui.clipboard.ClipboardManager
+import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
+import com.tangem.domain.walletconnect.usecase.sign.WcSignState
+import com.tangem.domain.walletconnect.usecase.sign.WcSignStep
+import com.tangem.domain.walletconnect.usecase.sign.WcSignUseCase
+import com.tangem.features.walletconnect.transaction.components.WcSignTransactionComponent
+import com.tangem.features.walletconnect.transaction.entity.WcSignTransactionUM
+import com.tangem.features.walletconnect.transaction.entity.WcTransactionActionsUM
+import com.tangem.features.walletconnect.transaction.utils.toUM
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@Stable
+@ModelScoped
+internal class WcSignTransactionModel @Inject constructor(
+ paramsContainer: ParamsContainer,
+ override val dispatchers: CoroutineDispatcherProvider,
+ private val router: Router,
+ private val clipboardManager: ClipboardManager,
+ private val useCaseFactory: WcRequestUseCaseFactory,
+) : Model() {
+
+ private val _uiState = MutableStateFlow(null)
+ val uiState: StateFlow = _uiState
+
+ private val params = paramsContainer.require()
+
+ init {
+ modelScope.launch {
+ val useCase: WcSignUseCase.SimpleRun<*> = useCaseFactory.createUseCase(params.rawRequest)
+ useCase.invoke()
+ .onEach { signState ->
+ if (signingIsDone(signState)) return@onEach
+ val signTransactionUM = (useCase as? WcSignUseCase)?.toUM(
+ signState = signState,
+ actions = WcTransactionActionsUM(
+ onDismiss = { cancel(useCase) },
+ onBack = ::showTransactionState,
+ onSign = useCase::sign,
+ onCopy = { copyData(useCase.rawSdkRequest.request.params) },
+ transactionRequestOnClick = ::showTransactionRequestState,
+ ),
+ )
+ _uiState.emit(signTransactionUM)
+ }
+ .launchIn(this)
+ }
+ }
+
+ private fun signingIsDone(signState: WcSignState<*>): Boolean {
+ (signState.domainStep as? WcSignStep.Result)?.result?.let {
+ router.pop()
+ return true
+ }
+ return false
+ }
+
+ private fun cancel(useCase: WcSignUseCase) {
+ useCase.cancel()
+ router.pop()
+ }
+
+ private fun copyData(text: String) {
+ clipboardManager.setText(text = text, isSensitive = true)
+ }
+
+ private fun showTransactionRequestState() {
+ _uiState.value = _uiState.value?.copy(state = WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO)
+ }
+
+ private fun showTransactionState() {
+ _uiState.value = _uiState.value?.copy(state = WcSignTransactionUM.State.TRANSACTION)
+ }
+}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/TransactionRequestInfoContent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/TransactionRequestInfoContent.kt
new file mode 100644
index 0000000000..d7c61d3af8
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/TransactionRequestInfoContent.kt
@@ -0,0 +1,64 @@
+package com.tangem.features.walletconnect.transaction.ui.common
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.unit.dp
+import com.tangem.core.ui.components.SecondaryButtonIconEnd
+import com.tangem.core.ui.extensions.resolveReference
+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.WcSignTransactionUM
+
+@Composable
+internal fun TransactionRequestInfoContent(state: WcSignTransactionUM) {
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .heightIn(min = 310.dp)
+ .padding(horizontal = TangemTheme.dimens.spacing16),
+ ) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .clip(RoundedCornerShape(TangemTheme.dimens.radius16))
+ .background(TangemTheme.colors.background.action)
+ .padding(
+ start = TangemTheme.dimens.spacing16,
+ end = TangemTheme.dimens.spacing16,
+ bottom = TangemTheme.dimens.spacing20,
+ ),
+ ) {
+ state.transactionRequestInfo.info.forEach { item ->
+ Text(
+ text = item.title.resolveReference(),
+ modifier = Modifier.padding(top = TangemTheme.dimens.spacing20),
+ style = TangemTheme.typography.subtitle2,
+ color = TangemTheme.colors.text.tertiary,
+ )
+ Text(
+ text = item.description,
+ modifier = Modifier.padding(top = TangemTheme.dimens.spacing4),
+ style = TangemTheme.typography.body2,
+ color = TangemTheme.colors.text.primary1,
+ )
+ }
+ }
+
+ SecondaryButtonIconEnd(
+ modifier = Modifier
+ .align(Alignment.BottomCenter)
+ .padding(bottom = TangemTheme.dimens.spacing20)
+ .fillMaxWidth(),
+ text = stringResourceSafe(R.string.wc_copy_data_button_text),
+ onClick = state.actions.onCopy,
+ iconResId = R.drawable.ic_copy_24,
+ )
+ }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000000..1f337688aa
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcNetworkItem.kt
@@ -0,0 +1,60 @@
+package com.tangem.features.walletconnect.transaction.ui.common
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+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 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.WcNetworkInfoUM
+
+@Composable
+internal fun WcNetworkItem(networkInfo: WcNetworkInfoUM, modifier: Modifier = Modifier) {
+ Row(
+ modifier = modifier,
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ 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.spacing4)
+ .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),
+ ) {
+ Text(
+ text = networkInfo.name,
+ style = TangemTheme.typography.body1,
+ color = TangemTheme.colors.text.tertiary,
+ )
+ 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),
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcRequestFromItem.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcRequestFromItem.kt
new file mode 100644
index 0000000000..a36d7b2365
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcRequestFromItem.kt
@@ -0,0 +1,22 @@
+package com.tangem.features.walletconnect.transaction.ui.common
+
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import com.tangem.core.ui.extensions.stringResourceSafe
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.features.walletconnect.impl.R
+
+@Composable
+fun RequestFromItem(modifier: Modifier = Modifier) {
+ Text(
+ modifier = modifier
+ .fillMaxWidth()
+ .padding(top = TangemTheme.dimens.spacing12, start = TangemTheme.dimens.spacing12),
+ text = stringResourceSafe(R.string.wc_request_from),
+ color = TangemTheme.colors.text.tertiary,
+ style = TangemTheme.typography.subtitle2,
+ )
+}
\ No newline at end of file
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
new file mode 100644
index 0000000000..27eec41927
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcTransactionRequestButtons.kt
@@ -0,0 +1,39 @@
+package com.tangem.features.walletconnect.transaction.ui.common
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import com.tangem.core.ui.components.PrimaryButtonIconEnd
+import com.tangem.core.ui.components.SecondaryButton
+import com.tangem.core.ui.extensions.stringResourceSafe
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.features.walletconnect.impl.R
+
+@Composable
+internal fun WcTransactionRequestButtons(
+ isLoading: Boolean,
+ onDismiss: () -> Unit,
+ onSign: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ Row(modifier = modifier, horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) {
+ SecondaryButton(
+ modifier = Modifier
+ .fillMaxWidth()
+ .weight(1f),
+ text = stringResourceSafe(R.string.common_cancel),
+ onClick = onDismiss,
+ )
+ PrimaryButtonIconEnd(
+ modifier = Modifier
+ .fillMaxWidth()
+ .weight(1f),
+ text = stringResourceSafe(R.string.wc_sign_message_button_text),
+ onClick = onSign,
+ iconResId = R.drawable.ic_tangem_24,
+ showProgress = isLoading,
+ )
+ }
+}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcTransactionRequestItem.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcTransactionRequestItem.kt
new file mode 100644
index 0000000000..00215b757a
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcTransactionRequestItem.kt
@@ -0,0 +1,43 @@
+package com.tangem.features.walletconnect.transaction.ui.common
+
+import androidx.annotation.DrawableRes
+import androidx.compose.foundation.layout.Row
+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.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import com.tangem.core.ui.extensions.stringResourceSafe
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.features.walletconnect.impl.R
+
+@Composable
+internal fun WcTransactionRequestItem(@DrawableRes iconRes: Int, modifier: Modifier = Modifier) {
+ Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
+ Icon(
+ modifier = Modifier.size(TangemTheme.dimens.size24),
+ painter = painterResource(iconRes),
+ contentDescription = null,
+ tint = TangemTheme.colors.icon.accent,
+ )
+ Text(
+ modifier = Modifier
+ .padding(start = TangemTheme.dimens.spacing4)
+ .weight(1f),
+ text = stringResourceSafe(R.string.wc_transaction_request),
+ style = TangemTheme.typography.body1,
+ color = TangemTheme.colors.text.primary1,
+ )
+ Icon(
+ modifier = Modifier
+ .padding(start = TangemTheme.dimens.spacing12)
+ .size(width = TangemTheme.dimens.size18, height = TangemTheme.dimens.size24),
+ painter = painterResource(R.drawable.ic_chevron_right_24),
+ contentDescription = null,
+ tint = TangemTheme.colors.icon.informative,
+ )
+ }
+}
\ 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
new file mode 100644
index 0000000000..63633a22c1
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/common/WcWalletItem.kt
@@ -0,0 +1,44 @@
+package com.tangem.features.walletconnect.transaction.ui.common
+
+import androidx.compose.foundation.layout.Row
+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.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.extensions.stringResourceSafe
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.features.walletconnect.impl.R
+
+@Composable
+internal fun WcWalletItem(walletName: String, modifier: Modifier = Modifier) {
+ Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
+ Icon(
+ modifier = Modifier.size(TangemTheme.dimens.size24),
+ painter = painterResource(R.drawable.ic_wallet_new_24),
+ 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,
+ )
+ }
+}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheet.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheet.kt
new file mode 100644
index 0000000000..665eb497b3
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheet.kt
@@ -0,0 +1,154 @@
+package com.tangem.features.walletconnect.transaction.ui.sign
+
+import android.content.res.Configuration
+import androidx.compose.animation.animateContentSize
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+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.datasource.CollectionPreviewParameterProvider
+import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
+import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
+import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
+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.*
+import com.tangem.features.walletconnect.transaction.ui.common.TransactionRequestInfoContent
+import kotlinx.collections.immutable.persistentListOf
+
+@Composable
+internal fun WcSignTransactionModalBottomSheet(config: TangemBottomSheetConfig) {
+ TangemModalBottomSheet(
+ config = config,
+ containerColor = TangemTheme.colors.background.tertiary,
+ title = { state ->
+ TangemModalBottomSheetTitle(
+ title = when (state.state) {
+ WcSignTransactionUM.State.TRANSACTION -> {
+ resourceReference(R.string.wallet_connect_title)
+ }
+ WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO -> {
+ resourceReference(R.string.wc_transaction_request_title)
+ }
+ },
+ endIconRes = state.endIconRes.takeIf {
+ state.state == WcSignTransactionUM.State.TRANSACTION
+ },
+ onEndClick = state.actions.onDismiss,
+ startIconRes = state.startIconRes.takeIf {
+ state.state == WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO
+ },
+ onStartClick = state.actions.onBack,
+ )
+ },
+ content = { state ->
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .animateContentSize(),
+ ) {
+ when (state.state) {
+ WcSignTransactionUM.State.TRANSACTION -> {
+ WcSignTransactionModalBottomSheetContent(state)
+ }
+ WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO -> {
+ TransactionRequestInfoContent(state)
+ }
+ }
+ }
+ },
+ )
+}
+
+@Composable
+@Preview(showBackground = true, device = Devices.PIXEL_7_PRO)
+@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES)
+private fun WcSignTransactionBottomSheetPreview(
+ @PreviewParameter(WcSignTransactionStateProvider::class) state: WcSignTransactionUM,
+) {
+ TangemThemePreview {
+ WcSignTransactionModalBottomSheet(
+ config = TangemBottomSheetConfig(
+ isShown = true,
+ onDismissRequest = {},
+ content = state,
+ ),
+ )
+ }
+}
+
+private class WcSignTransactionStateProvider : CollectionPreviewParameterProvider(
+ listOf(
+ WcSignTransactionUM(
+ startIconRes = R.drawable.ic_back_24,
+ endIconRes = R.drawable.ic_close_24,
+ transactionIconRes = R.drawable.ic_doc_new_24,
+ state = WcSignTransactionUM.State.TRANSACTION,
+ transaction = WcTransactionUM(
+ appName = "React App",
+ appIcon = "",
+ isVerified = true,
+ appSubtitle = "react-app.walletconnect.com",
+ walletName = "Tangem 2.0",
+ networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
+ ),
+ transactionRequestInfo = WcTransactionRequestInfoUM(
+ persistentListOf(
+ WcTransactionRequestInfoItemUM(
+ title = resourceReference(R.string.wc_signature_type),
+ description = "personal_sign",
+ ),
+ WcTransactionRequestInfoItemUM(
+ title = resourceReference(R.string.wc_contents),
+ description = "Hello! My name is John Dow. test@tange.com",
+ ),
+ ),
+ ),
+ actions = WcTransactionActionsUM(
+ onDismiss = {},
+ onBack = {},
+ onSign = {},
+ onCopy = {},
+ transactionRequestOnClick = {},
+ ),
+ ),
+ WcSignTransactionUM(
+ startIconRes = R.drawable.ic_back_24,
+ endIconRes = R.drawable.ic_close_24,
+ transactionIconRes = R.drawable.ic_doc_new_24,
+ state = WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO,
+ transaction = WcTransactionUM(
+ appName = "React App",
+ appIcon = "",
+ isVerified = true,
+ appSubtitle = "react-app.walletconnect.com",
+ walletName = "Tangem 2.0",
+ networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
+ ),
+ transactionRequestInfo = WcTransactionRequestInfoUM(
+ persistentListOf(
+ WcTransactionRequestInfoItemUM(
+ title = resourceReference(R.string.wc_signature_type),
+ description = "personal_sign",
+ ),
+ WcTransactionRequestInfoItemUM(
+ title = resourceReference(R.string.wc_contents),
+ description = "Hello! My name is John Dow. test@tange.com",
+ ),
+ ),
+ ),
+ actions = WcTransactionActionsUM(
+ onDismiss = {},
+ onBack = {},
+ onSign = {},
+ onCopy = {},
+ transactionRequestOnClick = {},
+ ),
+ ),
+ ),
+)
\ 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
new file mode 100644
index 0000000000..7548486b13
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/ui/sign/WcSignTransactionModalBottomSheetContent.kt
@@ -0,0 +1,89 @@
+package com.tangem.features.walletconnect.transaction.ui.sign
+
+import androidx.compose.animation.animateContentSize
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+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.material3.HorizontalDivider
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.features.walletconnect.connections.ui.WcAppInfoItem
+import com.tangem.features.walletconnect.transaction.entity.WcSignTransactionUM
+import com.tangem.features.walletconnect.transaction.ui.common.*
+import com.tangem.features.walletconnect.transaction.ui.common.WcNetworkItem
+import com.tangem.features.walletconnect.transaction.ui.common.WcTransactionRequestButtons
+import com.tangem.features.walletconnect.transaction.ui.common.WcTransactionRequestItem
+import com.tangem.features.walletconnect.transaction.ui.common.WcWalletItem
+
+@Composable
+internal fun WcSignTransactionModalBottomSheetContent(state: WcSignTransactionUM) {
+ Column(modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing16)) {
+ Column(
+ modifier = Modifier
+ .clip(RoundedCornerShape(TangemTheme.dimens.radius14))
+ .background(color = TangemTheme.colors.background.action)
+ .fillMaxWidth()
+ .animateContentSize(),
+ ) {
+ RequestFromItem()
+ WcAppInfoItem(
+ iconUrl = state.transaction.appIcon,
+ title = state.transaction.appName,
+ subtitle = state.transaction.appSubtitle,
+ isVerified = state.transaction.isVerified,
+ )
+ HorizontalDivider(
+ thickness = TangemTheme.dimens.size1,
+ color = TangemTheme.colors.stroke.primary,
+ )
+ WcTransactionRequestItem(
+ iconRes = state.transactionIconRes,
+ modifier = Modifier
+ .fillMaxWidth()
+ .clickable { state.actions.transactionRequestOnClick() }
+ .padding(TangemTheme.dimens.spacing12),
+ )
+ }
+ Column(modifier = Modifier.padding(top = TangemTheme.dimens.spacing16)) {
+ Column(
+ modifier = Modifier
+ .clip(RoundedCornerShape(TangemTheme.dimens.radius14))
+ .background(color = TangemTheme.colors.background.action)
+ .fillMaxWidth()
+ .animateContentSize(),
+ ) {
+ val itemsModifier = Modifier
+ .fillMaxWidth()
+ .padding(TangemTheme.dimens.spacing12)
+
+ HorizontalDivider(
+ thickness = TangemTheme.dimens.size1,
+ color = TangemTheme.colors.stroke.primary,
+ )
+ WcWalletItem(
+ modifier = itemsModifier,
+ walletName = state.transaction.walletName,
+ )
+ HorizontalDivider(
+ thickness = TangemTheme.dimens.size1,
+ color = TangemTheme.colors.stroke.primary,
+ )
+ WcNetworkItem(
+ modifier = itemsModifier,
+ networkInfo = state.transaction.networkInfo,
+ )
+ }
+ WcTransactionRequestButtons(
+ modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing16),
+ onDismiss = state.actions.onDismiss,
+ onSign = state.actions.onSign,
+ isLoading = state.transaction.isLoading,
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/utils/WcSignTransactionUtils.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/utils/WcSignTransactionUtils.kt
new file mode 100644
index 0000000000..563dbda856
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/utils/WcSignTransactionUtils.kt
@@ -0,0 +1,66 @@
+package com.tangem.features.walletconnect.transaction.utils
+
+import com.domain.blockaid.models.dapp.CheckDAppResult
+import com.tangem.core.ui.extensions.getActiveIconRes
+import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.domain.walletconnect.usecase.ethereum.WcEthMessageSignUseCase
+import com.tangem.domain.walletconnect.usecase.sign.WcSignState
+import com.tangem.domain.walletconnect.usecase.sign.WcSignStep
+import com.tangem.domain.walletconnect.usecase.sign.WcSignUseCase
+import com.tangem.features.walletconnect.impl.R
+import com.tangem.features.walletconnect.transaction.entity.WcNetworkInfoUM
+import com.tangem.features.walletconnect.transaction.entity.WcSignTransactionUM
+import com.tangem.features.walletconnect.transaction.entity.WcTransactionActionsUM
+import com.tangem.features.walletconnect.transaction.entity.WcTransactionRequestInfoItemUM
+import com.tangem.features.walletconnect.transaction.entity.WcTransactionRequestInfoUM
+import com.tangem.features.walletconnect.transaction.entity.WcTransactionUM
+import kotlinx.collections.immutable.persistentListOf
+
+internal fun WcSignUseCase.toUM(signState: WcSignState<*>, actions: WcTransactionActionsUM): WcSignTransactionUM? {
+ return when (this) {
+ is WcEthMessageSignUseCase -> {
+ ethMessageSignToUM(
+ signState = signState,
+ signModel = signState.signModel as WcEthMessageSignUseCase.SignModel,
+ actions = actions,
+ )
+ }
+ else -> null
+ }
+}
+
+private fun WcEthMessageSignUseCase.ethMessageSignToUM(
+ signState: WcSignState<*>,
+ signModel: WcEthMessageSignUseCase.SignModel,
+ actions: WcTransactionActionsUM,
+) = WcSignTransactionUM(
+ startIconRes = R.drawable.ic_back_24,
+ endIconRes = R.drawable.ic_close_24,
+ transactionIconRes = R.drawable.ic_doc_new_24,
+ state = WcSignTransactionUM.State.TRANSACTION,
+ actions = actions,
+ transaction = WcTransactionUM(
+ appName = session.sdkModel.appMetaData.name,
+ appIcon = session.sdkModel.appMetaData.url,
+ isVerified = session.securityStatus == CheckDAppResult.SAFE,
+ appSubtitle = session.sdkModel.appMetaData.description,
+ walletName = session.wallet.name,
+ networkInfo = WcNetworkInfoUM(
+ name = network.name,
+ iconRes = getActiveIconRes(network.id.value),
+ ),
+ isLoading = signState.domainStep == WcSignStep.Signing,
+ ),
+ transactionRequestInfo = WcTransactionRequestInfoUM(
+ persistentListOf(
+ WcTransactionRequestInfoItemUM(
+ title = resourceReference(R.string.wc_signature_type),
+ description = rawSdkRequest.request.method,
+ ),
+ WcTransactionRequestInfoItemUM(
+ title = resourceReference(R.string.wc_contents),
+ description = signModel.humanMsg,
+ ),
+ ),
+ ),
+)
\ No newline at end of file