Updated on 2026-08-14

This commit is contained in:
Tangem 2025-05-28 22:51:59 +04:00
parent 4ae2342c19
commit f2f8a21d25
14 changed files with 187 additions and 18 deletions

View file

@ -18,6 +18,8 @@ import com.tangem.features.walletconnect.components.WcRoutingComponent
import com.tangem.features.walletconnect.connections.components.WcPairComponent
import com.tangem.features.walletconnect.connections.components.AlertsComponent
import com.tangem.features.walletconnect.transaction.components.chain.WcAddNetworkContainerComponent
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
import com.tangem.features.walletconnect.transaction.components.send.WcSendTransactionContainerComponent
import com.tangem.features.walletconnect.transaction.components.sign.WcSignTransactionContainerComponent
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -59,11 +61,15 @@ internal class DefaultWcRoutingComponent @AssistedInject constructor(
return when (config) {
is WcInnerRoute.SignMessage -> WcSignTransactionContainerComponent(
appComponentContext = childContext,
params = WcSignTransactionContainerComponent.Params(config.rawRequest),
params = WcTransactionModelParams(config.rawRequest),
)
is WcInnerRoute.AddNetwork -> WcAddNetworkContainerComponent(
appComponentContext = childContext,
params = WcAddNetworkContainerComponent.Params(config.rawRequest),
params = WcTransactionModelParams(config.rawRequest),
)
is WcInnerRoute.Send -> WcSendTransactionContainerComponent(
appComponentContext = childContext,
params = WcTransactionModelParams(config.rawRequest),
)
is WcInnerRoute.Pair -> WcPairComponent(
appComponentContext = childContext,

View file

@ -14,6 +14,9 @@ internal sealed interface WcInnerRoute : Route {
val rawRequest: WcSdkSessionRequest
}
@Serializable
data class Send(override val rawRequest: WcSdkSessionRequest) : Method
@Serializable
data class SignMessage(override val rawRequest: WcSdkSessionRequest) : Method

View file

@ -56,6 +56,7 @@ internal class WcRoutingModel @Inject constructor(
WcEthMethodName.SendTransaction,
WcSolanaMethodName.SignTransaction,
WcSolanaMethodName.SendAllTransaction,
-> WcInnerRoute.Send(rawRequest)
is WcMethodName.Unsupported,
-> WcInnerRoute.Alert(
alertType = AlertsComponent.AlertType.UnsupportedMethod { innerRouter.pop() },

View file

@ -4,6 +4,8 @@ import com.tangem.core.decompose.di.ModelComponent
import com.tangem.core.decompose.model.Model
import com.tangem.features.walletconnect.connections.model.*
import com.tangem.features.walletconnect.connections.routing.WcRoutingModel
import com.tangem.features.walletconnect.transaction.model.WcAddNetworkModel
import com.tangem.features.walletconnect.transaction.model.WcSendTransactionModel
import com.tangem.features.walletconnect.transaction.model.WcSignTransactionModel
import dagger.Binds
import dagger.Module
@ -49,4 +51,14 @@ internal interface WalletConnectModelModule {
@IntoMap
@ClassKey(WcSignTransactionModel::class)
fun bindWcSignTransactionModel(model: WcSignTransactionModel): Model
@Binds
@IntoMap
@ClassKey(WcAddNetworkModel::class)
fun bindWcAddNetworkModel(model: WcAddNetworkModel): Model
@Binds
@IntoMap
@ClassKey(WcSendTransactionModel::class)
fun bindWcSendTransactionModel(model: WcSendTransactionModel): Model
}

View file

@ -16,14 +16,14 @@ import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.decompose.navigation.inner.InnerRouter
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionRequestInfoComponent
import com.tangem.features.walletconnect.transaction.model.WcAddNetworkModel
import com.tangem.features.walletconnect.transaction.routes.WcTransactionRoutes
internal class WcAddNetworkContainerComponent(
private val appComponentContext: AppComponentContext,
params: Params,
params: WcTransactionModelParams,
) : AppComponentContext by appComponentContext, ComposableContentComponent {
private val contentNavigation = StackNavigation<WcTransactionRoutes>()
@ -31,7 +31,7 @@ internal class WcAddNetworkContainerComponent(
stackNavigation = contentNavigation,
popCallback = { onChildBack() },
)
private val model: WcAddNetworkModel = getOrCreateModel(params = params, router = innerRouter)
private val model: WcAddNetworkModel = getOrCreateModel(params = params)
private val contentStack = childStack(
key = "WcAddNetworkStack",
source = contentNavigation,
@ -82,6 +82,4 @@ internal class WcAddNetworkContainerComponent(
)
}
}
data class Params(val rawRequest: WcSdkSessionRequest)
}

View file

@ -0,0 +1,5 @@
package com.tangem.features.walletconnect.transaction.components.common
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
internal data class WcTransactionModelParams(val rawRequest: WcSdkSessionRequest)

View file

@ -0,0 +1,35 @@
package com.tangem.features.walletconnect.transaction.components.send
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.features.walletconnect.transaction.model.WcSendTransactionModel
import com.tangem.features.walletconnect.transaction.ui.send.WcSendTransactionModalBottomSheet
internal class WcSendTransactionComponent(
private val appComponentContext: AppComponentContext,
private val model: WcSendTransactionModel,
private val transactionInfoOnClick: () -> Unit,
private val onDismiss: () -> Unit,
) : AppComponentContext by appComponentContext, ComposableBottomSheetComponent {
override fun dismiss() {
onDismiss()
}
@Composable
override fun BottomSheet() {
val content by model.uiState.collectAsStateWithLifecycle()
if (content != null) {
WcSendTransactionModalBottomSheet(
state = content!!.transaction,
onClickTransactionRequest = transactionInfoOnClick,
onBack = router::pop,
onDismiss = ::dismiss,
)
}
}
}

View file

@ -0,0 +1,85 @@
package com.tangem.features.walletconnect.transaction.components.send
import androidx.activity.compose.BackHandler
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.extensions.compose.subscribeAsState
import com.arkivanov.decompose.router.stack.StackNavigation
import com.arkivanov.decompose.router.stack.childStack
import com.arkivanov.decompose.router.stack.pop
import com.arkivanov.decompose.router.stack.pushNew
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.context.childByContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.decompose.navigation.inner.InnerRouter
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionRequestInfoComponent
import com.tangem.features.walletconnect.transaction.model.WcSendTransactionModel
import com.tangem.features.walletconnect.transaction.routes.WcTransactionRoutes
internal class WcSendTransactionContainerComponent(
private val appComponentContext: AppComponentContext,
params: WcTransactionModelParams,
) : AppComponentContext by appComponentContext, ComposableContentComponent {
private val contentNavigation = StackNavigation<WcTransactionRoutes>()
private val innerRouter = InnerRouter<WcTransactionRoutes>(
stackNavigation = contentNavigation,
popCallback = { onChildBack() },
)
private val model: WcSendTransactionModel = getOrCreateModel(params = params)
private val contentStack = childStack(
key = "WcSendTransactionStack",
source = contentNavigation,
serializer = WcTransactionRoutes.serializer(),
initialConfiguration = WcTransactionRoutes.Transaction,
handleBackButton = true,
childFactory = ::screenChild,
)
@Composable
override fun Content(modifier: Modifier) {
val content by contentStack.subscribeAsState()
BackHandler(onBack = ::onChildBack)
content.active.instance.BottomSheet()
}
private fun dismiss() {
router.pop()
}
private fun onChildBack() {
when (contentStack.value.active.configuration) {
WcTransactionRoutes.Transaction -> contentNavigation.pop()
WcTransactionRoutes.TransactionRequestInfo -> contentNavigation.pushNew(WcTransactionRoutes.Transaction)
}
}
private fun toTransactionRequestInfo() {
contentNavigation.pushNew(WcTransactionRoutes.TransactionRequestInfo)
}
private fun screenChild(
config: WcTransactionRoutes,
componentContext: ComponentContext,
): ComposableBottomSheetComponent {
val appComponentContext = childByContext(componentContext = componentContext, router = innerRouter)
return when (config) {
is WcTransactionRoutes.Transaction -> WcSendTransactionComponent(
appComponentContext = childByContext(componentContext),
transactionInfoOnClick = ::toTransactionRequestInfo,
onDismiss = ::dismiss,
model = model,
)
is WcTransactionRoutes.TransactionRequestInfo -> WcTransactionRequestInfoComponent(
appComponentContext = appComponentContext,
onDismiss = ::dismiss,
model = model.uiState.value?.transactionRequestInfo,
)
}
}
}

View file

@ -13,14 +13,14 @@ import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.decompose.navigation.inner.InnerRouter
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionRequestInfoComponent
import com.tangem.features.walletconnect.transaction.model.WcSignTransactionModel
import com.tangem.features.walletconnect.transaction.routes.WcTransactionRoutes
internal class WcSignTransactionContainerComponent(
private val appComponentContext: AppComponentContext,
params: Params,
params: WcTransactionModelParams,
) : AppComponentContext by appComponentContext, ComposableContentComponent {
private val contentNavigation = StackNavigation<WcTransactionRoutes>()
@ -28,7 +28,7 @@ internal class WcSignTransactionContainerComponent(
stackNavigation = contentNavigation,
popCallback = { onChildBack() },
)
private val model: WcSignTransactionModel = getOrCreateModel(params = params, router = innerRouter)
private val model: WcSignTransactionModel = getOrCreateModel(params = params)
private val contentStack = childStack(
key = "WcSignTransactionStack",
source = contentNavigation,
@ -72,6 +72,4 @@ internal class WcSignTransactionContainerComponent(
)
}
}
data class Params(val rawRequest: WcSdkSessionRequest)
}

View file

@ -9,7 +9,7 @@ import com.tangem.core.ui.clipboard.ClipboardManager
import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
import com.tangem.domain.walletconnect.usecase.method.WcAddNetworkUseCase
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
import com.tangem.features.walletconnect.transaction.components.sign.WcSignTransactionContainerComponent
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
import com.tangem.features.walletconnect.transaction.entity.chain.WcAddEthereumChainUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
import com.tangem.features.walletconnect.transaction.utils.toUM
@ -33,7 +33,7 @@ internal class WcAddNetworkModel @Inject constructor(
private val _uiState = MutableStateFlow<WcAddEthereumChainUM?>(null)
val uiState: StateFlow<WcAddEthereumChainUM?> = _uiState
private val params = paramsContainer.require<WcSignTransactionContainerComponent.Params>()
private val params = paramsContainer.require<WcTransactionModelParams>()
init {
modelScope.launch {

View file

@ -0,0 +1,24 @@
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.features.walletconnect.transaction.entity.send.WcSendTransactionUM
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import javax.inject.Inject
@Stable
@ModelScoped
internal class WcSendTransactionModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
) : Model() {
private val _uiState = MutableStateFlow<WcSendTransactionUM?>(null)
val uiState: StateFlow<WcSendTransactionUM?> = _uiState
init {
TODO("Finish model in this task [REDACTED_JIRA]")
}
}

View file

@ -10,7 +10,7 @@ import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
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.sign.WcSignTransactionContainerComponent
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionUM
import com.tangem.features.walletconnect.transaction.utils.toUM
@ -35,7 +35,7 @@ internal class WcSignTransactionModel @Inject constructor(
private val _uiState = MutableStateFlow<WcSignTransactionUM?>(null)
val uiState: StateFlow<WcSignTransactionUM?> = _uiState
private val params = paramsContainer.require<WcSignTransactionContainerComponent.Params>()
private val params = paramsContainer.require<WcTransactionModelParams>()
init {
modelScope.launch {

View file

@ -59,7 +59,7 @@ internal fun TransactionRequestInfoContent(
TangemModalBottomSheetTitle(
title = resourceReference(R.string.wc_transaction_request_title),
startIconRes = R.drawable.ic_back_24,
onStartClick = onDismiss,
onStartClick = onBack,
)
},
content = {

View file

@ -42,6 +42,7 @@ import kotlinx.collections.immutable.persistentListOf
internal fun WcSendTransactionModalBottomSheet(
state: WcSendTransactionItemUM,
onClickTransactionRequest: () -> Unit,
onBack: () -> Unit,
onDismiss: () -> Unit,
) {
TangemModalBottomSheetWithFooter<TangemBottomSheetConfigContent.Empty>(
@ -50,6 +51,7 @@ internal fun WcSendTransactionModalBottomSheet(
onDismissRequest = onDismiss,
content = TangemBottomSheetConfigContent.Empty,
),
onBack = onBack,
containerColor = TangemTheme.colors.background.tertiary,
title = { config ->
TangemModalBottomSheetTitle(
@ -134,7 +136,7 @@ private fun WcSendTransactionBottomSheetPreview(
)
},
content = {
WcSendTransactionModalBottomSheet(state = state, onClickTransactionRequest = {}, onDismiss = {})
WcSendTransactionModalBottomSheet(state, {}, {}, {})
},
)
}