diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index c81754117c..ec20bf2c8f 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -1505,12 +1505,16 @@
Enable Trustline
A Trustline must be enabled to receive this token. The network requires a %1$s %2$s reserve.
Trustline Required
+ The required network %s is not added to your portfolio. Add it first, then proceed with the connection.
+ Add network to portfolio
Malicious domain
Unknown domain
Connect anyway
Timeout error. Please, try again later.
Failed to establish WalletConnect
This domain cannot be verified. Check the request carefully approving.
+ To continue, please reconnect your dApp session with the required network %s.
+ Network not connected
Please return to your browser and reconnect via WalletConnect.
Wallet Connect session was disconnected
Sign anyway
@@ -1521,6 +1525,8 @@
Unsupported dApp
Error code: 8 005. If the problem persists — feel free to contact our support.
We\'ve encountered unknown error
+ This network %s is not supported by Tangem Wallet and cannot be connected.
+ Unsupported network
Tangem does not currently support a required network by %s.
Unsupported networks
This domain has passed verification checks and is considered safe, reputable, and free from known threats or suspicious activity. %s
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthAddNetworkUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthAddNetworkUseCase.kt
index 0bc201fd7a..5c988f8a8e 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthAddNetworkUseCase.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthAddNetworkUseCase.kt
@@ -1,9 +1,17 @@
package com.tangem.data.walletconnect.network.ethereum
import arrow.core.Either
+import arrow.core.left
+import arrow.core.right
+import com.tangem.blockchain.extensions.hexToInt
+import com.tangem.data.walletconnect.model.CAIP2
+import com.tangem.data.walletconnect.network.ethereum.WcEthNetwork.NamespaceConverter.Companion.ETH_NAMESPACE_KEY
import com.tangem.data.walletconnect.respond.WcRespondService
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
+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.HandleMethodError
import com.tangem.domain.walletconnect.model.WcEthMethod
import com.tangem.domain.walletconnect.model.WcRequestError
import com.tangem.domain.walletconnect.model.WcSession
@@ -16,6 +24,7 @@ import dagger.assisted.AssistedInject
internal class WcEthAddNetworkUseCase @AssistedInject constructor(
private val respondService: WcRespondService,
+ addSwitchCommonDelegateFactory: WcEthAddSwitchCommonDelegate.Factory,
@Assisted val context: WcMethodUseCaseContext,
@Assisted override val method: WcEthMethod.AddEthereumChain,
) : WcAddNetworkUseCase {
@@ -31,6 +40,14 @@ internal class WcEthAddNetworkUseCase @AssistedInject constructor(
else -> WcNetworkDerivationState.Single
}
+ private val addSwitchCommonDelegate = addSwitchCommonDelegateFactory.create(context)
+
+ override suspend fun invoke(): Either {
+ return addSwitchCommonDelegate
+ .commonChecks(method.rawChain.chainId)
+ .map { addedNetwork -> WcAddNetworkUseCase.AddNetwork(addedNetwork) }
+ }
+
override suspend fun approve(): Either {
return respondService.respond(rawSdkRequest, "")
}
@@ -43,4 +60,31 @@ internal class WcEthAddNetworkUseCase @AssistedInject constructor(
interface Factory {
fun create(context: WcMethodUseCaseContext, method: WcEthMethod.AddEthereumChain): WcEthAddNetworkUseCase
}
+}
+
+internal class WcEthAddSwitchCommonDelegate @AssistedInject constructor(
+ private val networksConverter: WcNetworksConverter,
+ @Assisted val context: WcMethodUseCaseContext,
+) {
+
+ private val wallet: UserWallet get() = context.session.wallet
+
+ suspend fun commonChecks(hexChainId: String): Either {
+ val caip2 = CAIP2.fromRaw("$ETH_NAMESPACE_KEY:${hexChainId.hexToInt()}")
+ ?: return HandleMethodError.UnknownError("Failed to parse CAIP2").left()
+ val generalNetwork = networksConverter.createNetwork(caip2.raw, wallet)
+ if (generalNetwork == null) {
+ return HandleMethodError.TangemUnsupportedNetwork(caip2.raw).left()
+ }
+ val addedNetwork = networksConverter.mainOrAnyWalletNetworkForRequest(caip2.raw, wallet)
+ if (addedNetwork == null) {
+ return HandleMethodError.NotAddedNetwork(generalNetwork.name).left()
+ }
+ return addedNetwork.right()
+ }
+
+ @AssistedFactory
+ interface Factory {
+ fun create(context: WcMethodUseCaseContext): WcEthAddSwitchCommonDelegate
+ }
}
\ No newline at end of file
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 fe375b57d6..a14460a566 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
@@ -6,17 +6,14 @@ import arrow.core.left
import arrow.core.right
import com.squareup.moshi.Moshi
import com.tangem.blockchain.common.Blockchain
-import com.tangem.blockchain.extensions.hexToInt
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
import com.tangem.data.walletconnect.model.CAIP2
import com.tangem.data.walletconnect.model.NamespaceKey
-import com.tangem.data.walletconnect.network.ethereum.WcEthNetwork.NamespaceConverter.Companion.ETH_NAMESPACE_KEY
import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter
import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter.Companion.fromJson
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.wallet.UserWallet
import com.tangem.domain.walletconnect.model.*
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.repository.WcSessionsManager
@@ -46,7 +43,7 @@ internal class WcEthNetwork(
?: return HandleMethodError.UnknownSession.left()
val wallet = session.wallet
val chainId = request.chainId.orEmpty()
- val method: WcEthMethod = name.toMethod(request, wallet)
+ val method: WcEthMethod = name.toMethod(request)
.getOrElse { return error(it.message.orEmpty()) }
?: return error("Failed to parse $name")
suspend fun anyExistNetwork() = networksConverter.mainOrAnyWalletNetworkForRequest(chainId, wallet)
@@ -56,7 +53,9 @@ internal class WcEthNetwork(
is WcEthMethod.SendTransaction -> method.transaction.from
is WcEthMethod.SignTransaction -> method.transaction.from
is WcEthMethod.SignTypedData -> method.account
- is WcEthMethod.AddEthereumChain ->
+ is WcEthMethod.AddEthereumChain,
+ is WcEthMethod.SwitchEthereumChain,
+ ->
anyExistNetwork()
?.let { network -> walletManagersFacade.getDefaultAddress(wallet.walletId, network).orEmpty() }
.orEmpty()
@@ -67,7 +66,9 @@ internal class WcEthNetwork(
is WcEthMethod.SendTransaction,
is WcEthMethod.SignTransaction,
-> networksConverter.findWalletNetworkForRequest(request, session, accountAddress)
- is WcEthMethod.AddEthereumChain -> anyExistNetwork()
+ is WcEthMethod.AddEthereumChain,
+ is WcEthMethod.SwitchEthereumChain,
+ -> anyExistNetwork()
} ?: return error("Failed to find walletNetwork for accountAddress $accountAddress")
val context = WcMethodUseCaseContext(
@@ -83,13 +84,11 @@ internal class WcEthNetwork(
is WcEthMethod.SignTransaction -> factories.signTransaction.create(context, method)
is WcEthMethod.SignTypedData -> factories.signTypedData.create(context, method)
is WcEthMethod.AddEthereumChain -> factories.addNetwork.create(context, method)
+ is WcEthMethod.SwitchEthereumChain -> factories.switchNetwork.create(context, method)
}.right()
}
- private suspend fun WcEthMethodName.toMethod(
- request: WcSdkSessionRequest,
- wallet: UserWallet,
- ): Either {
+ private fun WcEthMethodName.toMethod(request: WcSdkSessionRequest): Either {
val rawParams = request.request.params
return when (this) {
WcEthMethodName.EthSign,
@@ -111,16 +110,17 @@ internal class WcEthNetwork(
}
}
?: return null.right()
- WcEthMethodName.AddEthereumChain -> moshi.fromJson>(rawParams)
+ WcEthMethodName.AddEthereumChain,
+ WcEthMethodName.SwitchEthereumChain,
+ -> moshi.fromJson>(rawParams)
.getOrElse { return it.left() }
?.firstOrNull()
?.let {
- val caip2 = CAIP2.fromRaw("$ETH_NAMESPACE_KEY:${it.chainId.hexToInt()}")
- ?: return null.right()
- val newNetwork = networksConverter
- .mainOrAnyWalletNetworkForRequest(caip2.raw, wallet)
- ?: return null.right()
- WcEthMethod.AddEthereumChain(rawChain = it, network = newNetwork).right()
+ if (this == WcEthMethodName.AddEthereumChain) {
+ WcEthMethod.AddEthereumChain(rawChain = it).right()
+ } else {
+ WcEthMethod.SwitchEthereumChain(rawChain = it).right()
+ }
}
?: null.right()
}
@@ -170,5 +170,6 @@ internal class WcEthNetwork(
val sendTransaction: WcEthSendTransactionUseCase.Factory,
val signTransaction: WcEthSignTransactionUseCase.Factory,
val addNetwork: WcEthAddNetworkUseCase.Factory,
+ val switchNetwork: WcEthSwitchNetworkUseCase.Factory,
)
}
\ No newline at end of file
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSwitchNetworkUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSwitchNetworkUseCase.kt
new file mode 100644
index 0000000000..0835594dfe
--- /dev/null
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSwitchNetworkUseCase.kt
@@ -0,0 +1,51 @@
+package com.tangem.data.walletconnect.network.ethereum
+
+import arrow.core.Either
+import com.tangem.data.walletconnect.respond.WcRespondService
+import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
+import com.tangem.domain.models.network.Network
+import com.tangem.domain.walletconnect.model.HandleMethodError
+import com.tangem.domain.walletconnect.model.WcEthMethod
+import com.tangem.domain.walletconnect.model.WcSession
+import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
+import com.tangem.domain.walletconnect.usecase.method.WcNetworkDerivationState
+import com.tangem.domain.walletconnect.usecase.method.WcSwitchNetworkUseCase
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+
+internal class WcEthSwitchNetworkUseCase @AssistedInject constructor(
+ private val respondService: WcRespondService,
+ @Assisted val context: WcMethodUseCaseContext,
+ @Assisted override val method: WcEthMethod.SwitchEthereumChain,
+ addSwitchCommonDelegateFactory: WcEthAddSwitchCommonDelegate.Factory,
+) : WcSwitchNetworkUseCase {
+
+ override val session: WcSession
+ get() = context.session
+ override val rawSdkRequest: WcSdkSessionRequest
+ get() = context.rawSdkRequest
+ override val network: Network
+ get() = context.network
+ override val derivationState: WcNetworkDerivationState = when {
+ context.networkDerivationsCount > 1 -> WcNetworkDerivationState.Multiple(walletAddress = context.accountAddress)
+ else -> WcNetworkDerivationState.Single
+ }
+
+ private val addSwitchCommonDelegate = addSwitchCommonDelegateFactory.create(context)
+
+ override suspend fun invoke(): Either {
+ return addSwitchCommonDelegate
+ .commonChecks(method.rawChain.chainId)
+ .map { addedNetwork -> WcSwitchNetworkUseCase.SwitchNetwork(addedNetwork) }
+ }
+
+ override fun reject() {
+ respondService.rejectRequestNonBlock(rawSdkRequest)
+ }
+
+ @AssistedFactory
+ interface Factory {
+ fun create(context: WcMethodUseCaseContext, method: WcEthMethod.SwitchEthereumChain): WcEthSwitchNetworkUseCase
+ }
+}
\ No newline at end of file
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/request/DefaultWcRequestService.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/request/DefaultWcRequestService.kt
index 4c50b189fd..db8788c05a 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/request/DefaultWcRequestService.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/request/DefaultWcRequestService.kt
@@ -33,6 +33,7 @@ internal class DefaultWcRequestService(
Timber.tag(WC_TAG).i("handle request name $name")
if (name is WcMethodName.Unsupported) {
respondService.rejectRequestNonBlock(sr)
+ if (name.raw.startsWith("wallet_")) return
}
_wcRequest.trySend(name to sr)
}
diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNetworksConverter.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNetworksConverter.kt
index 6a80763cc9..4b49445c7f 100644
--- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNetworksConverter.kt
+++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNetworksConverter.kt
@@ -25,6 +25,11 @@ internal class WcNetworksConverter @Inject constructor(
private val tokensFeatureToggles: TokensFeatureToggles,
) {
+ fun createNetwork(chainId: String, wallet: UserWallet): Network? {
+ return namespaceConverters
+ .firstNotNullOfOrNull { it.toNetwork(chainId, wallet) }
+ }
+
suspend fun findWalletNetworkForRequest(
request: WcSdkSessionRequest,
session: WcSession,
diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcEthMethod.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcEthMethod.kt
index afb348e77e..34b43e11bb 100644
--- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcEthMethod.kt
+++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcEthMethod.kt
@@ -1,7 +1,5 @@
package com.tangem.domain.walletconnect.model
-import com.tangem.domain.models.network.Network
-
sealed interface WcEthMethod : WcMethod {
data class MessageSign(
@@ -28,6 +26,9 @@ sealed interface WcEthMethod : WcMethod {
data class AddEthereumChain(
val rawChain: WcEthAddChain,
- val network: Network,
+ ) : WcEthMethod
+
+ data class SwitchEthereumChain(
+ val rawChain: WcEthAddChain,
) : WcEthMethod
}
\ No newline at end of file
diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcMethodName.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcMethodName.kt
index 6ae4b431ac..982c1cacf1 100644
--- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcMethodName.kt
+++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcMethodName.kt
@@ -14,6 +14,7 @@ enum class WcEthMethodName(override val raw: String) : WcMethodName {
SignTransaction("eth_signTransaction"),
SendTransaction("eth_sendTransaction"),
AddEthereumChain("wallet_addEthereumChain"),
+ SwitchEthereumChain("wallet_switchEthereumChain"),
}
enum class WcSolanaMethodName(override val raw: String) : WcMethodName {
diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcRequestError.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcRequestError.kt
index 3c1cfe610a..e0ad853f77 100644
--- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcRequestError.kt
+++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcRequestError.kt
@@ -69,4 +69,9 @@ sealed class HandleMethodError(
data object UnknownSession : HandleMethodError(message = "WalletConnect session was disconnected")
data class UnknownError(override val message: String) : HandleMethodError(message)
+ data class TangemUnsupportedNetwork(val unsupportedNetwork: String) :
+ HandleMethodError("TangemUnsupportedNetwork $unsupportedNetwork")
+
+ data class NotAddedNetwork(val networkName: String) : HandleMethodError("NotAddedNetwork $networkName")
+ data class RequiredNetwork(val networkName: String) : HandleMethodError("RequiredNetwork $networkName")
}
\ No newline at end of file
diff --git a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcAddNetworkUseCase.kt b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcAddNetworkUseCase.kt
index 787bea6e93..35223ba040 100644
--- a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcAddNetworkUseCase.kt
+++ b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcAddNetworkUseCase.kt
@@ -1,12 +1,19 @@
package com.tangem.domain.walletconnect.usecase.method
import arrow.core.Either
+import com.tangem.domain.models.network.Network
+import com.tangem.domain.walletconnect.model.HandleMethodError
import com.tangem.domain.walletconnect.model.WcRequestError
interface WcAddNetworkUseCase :
WcMethodUseCase,
WcMethodContext {
+ suspend operator fun invoke(): Either
suspend fun approve(): Either
fun reject()
+
+ data class AddNetwork(
+ val network: Network,
+ )
}
\ No newline at end of file
diff --git a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcSwitchNetworkUseCase.kt b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcSwitchNetworkUseCase.kt
new file mode 100644
index 0000000000..5c2066049a
--- /dev/null
+++ b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcSwitchNetworkUseCase.kt
@@ -0,0 +1,17 @@
+package com.tangem.domain.walletconnect.usecase.method
+
+import arrow.core.Either
+import com.tangem.domain.models.network.Network
+import com.tangem.domain.walletconnect.model.HandleMethodError
+
+interface WcSwitchNetworkUseCase :
+ WcMethodUseCase,
+ WcMethodContext {
+
+ suspend operator fun invoke(): Either
+ fun reject()
+
+ data class SwitchNetwork(
+ val network: Network,
+ )
+}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/AlertsComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/AlertsComponent.kt
index 6fd6fde73b..fd682083d3 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/AlertsComponent.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/AlertsComponent.kt
@@ -38,5 +38,23 @@ internal class AlertsComponent(
@Serializable
data class WcDisconnected(override val onDismiss: () -> Unit) : AlertType()
+
+ @Serializable
+ data class TangemUnsupportedNetwork(
+ val network: String,
+ override val onDismiss: () -> Unit,
+ ) : AlertType()
+
+ @Serializable
+ data class RequiredAddNetwork(
+ val network: String,
+ override val onDismiss: () -> Unit,
+ ) : AlertType()
+
+ @Serializable
+ data class RequiredReconnectWithNetwork(
+ val network: String,
+ override val onDismiss: () -> Unit,
+ ) : AlertType()
}
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/DefaultWcRoutingComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/DefaultWcRoutingComponent.kt
index 42b336932f..30c6d10c14 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/DefaultWcRoutingComponent.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/DefaultWcRoutingComponent.kt
@@ -18,8 +18,10 @@ import com.tangem.features.send.v2.api.FeeSelectorBlockComponent
import com.tangem.features.send.v2.api.FeeSelectorComponent
import com.tangem.features.walletconnect.components.WcRoutingComponent
import com.tangem.features.walletconnect.connections.components.AlertsComponent
+import com.tangem.features.walletconnect.connections.components.AlertsComponent.AlertType.*
import com.tangem.features.walletconnect.connections.components.WcPairComponent
import com.tangem.features.walletconnect.transaction.components.chain.WcAddNetworkContainerComponent
+import com.tangem.features.walletconnect.transaction.components.chain.WcSwitchNetworkComponent
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
@@ -71,6 +73,10 @@ internal class DefaultWcRoutingComponent @AssistedInject constructor(
appComponentContext = childContext,
params = WcTransactionModelParams(config.rawRequest),
)
+ is WcInnerRoute.SwitchNetwork -> WcSwitchNetworkComponent(
+ appComponentContext = childContext,
+ params = WcTransactionModelParams(config.rawRequest),
+ )
is WcInnerRoute.Send -> WcSendTransactionContainerComponent(
appComponentContext = childContext,
params = WcTransactionModelParams(config.rawRequest),
@@ -88,13 +94,31 @@ internal class DefaultWcRoutingComponent @AssistedInject constructor(
is WcInnerRoute.UnsupportedMethodAlert -> AlertsComponent(
childContext,
AlertsComponent.Params(
- alertType = AlertsComponent.AlertType.UnsupportedMethod { model.innerRouter.pop() },
+ alertType = UnsupportedMethod { model.innerRouter.pop() },
),
)
is WcInnerRoute.WcDappDisconnected -> AlertsComponent(
childContext,
AlertsComponent.Params(
- alertType = AlertsComponent.AlertType.WcDisconnected { model.innerRouter.pop() },
+ alertType = WcDisconnected { model.innerRouter.pop() },
+ ),
+ )
+ is WcInnerRoute.TangemUnsupportedNetwork -> AlertsComponent(
+ childContext,
+ AlertsComponent.Params(
+ alertType = TangemUnsupportedNetwork(config.networkName) { model.innerRouter.pop() },
+ ),
+ )
+ is WcInnerRoute.RequiredAddNetwork -> AlertsComponent(
+ childContext,
+ AlertsComponent.Params(
+ alertType = RequiredAddNetwork(config.networkName) { model.innerRouter.pop() },
+ ),
+ )
+ is WcInnerRoute.RequiredReconnectWithNetwork -> AlertsComponent(
+ childContext,
+ AlertsComponent.Params(
+ alertType = RequiredReconnectWithNetwork(config.networkName) { model.innerRouter.pop() },
),
)
}
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/WcInnerRoute.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/WcInnerRoute.kt
index 4cabfc0547..bc9f386e88 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/WcInnerRoute.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/WcInnerRoute.kt
@@ -22,6 +22,9 @@ internal sealed interface WcInnerRoute : Route {
@Serializable
data class AddNetwork(override val rawRequest: WcSdkSessionRequest) : Method
+ @Serializable
+ data class SwitchNetwork(override val rawRequest: WcSdkSessionRequest) : Method
+
@Serializable
data class Pair(val request: WcPairRequest) : WcInnerRoute
@@ -30,4 +33,13 @@ internal sealed interface WcInnerRoute : Route {
@Serializable
data object WcDappDisconnected : WcInnerRoute
+
+ @Serializable
+ data class TangemUnsupportedNetwork(val networkName: String) : WcInnerRoute
+
+ @Serializable
+ data class RequiredAddNetwork(val networkName: String) : WcInnerRoute
+
+ @Serializable
+ data class RequiredReconnectWithNetwork(val networkName: String) : WcInnerRoute
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/WcRoutingModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/WcRoutingModel.kt
index 3c320faab7..5524f954e3 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/WcRoutingModel.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routing/WcRoutingModel.kt
@@ -51,6 +51,8 @@ internal class WcRoutingModel @Inject constructor(
-> WcInnerRoute.SignMessage(rawRequest)
WcEthMethodName.AddEthereumChain,
-> WcInnerRoute.AddNetwork(rawRequest)
+ WcEthMethodName.SwitchEthereumChain,
+ -> WcInnerRoute.SwitchNetwork(rawRequest)
WcEthMethodName.SignTransaction,
WcEthMethodName.SendTransaction,
WcSolanaMethodName.SignTransaction,
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/AlertsModalBottomSheet.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/AlertsModalBottomSheet.kt
index 7c93a184f5..c7ff306829 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/AlertsModalBottomSheet.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/AlertsModalBottomSheet.kt
@@ -87,7 +87,11 @@ private fun ButtonsContainer(alert: AlertsComponent.AlertType, modifier: Modifie
) {
val buttonsModifier = Modifier.fillMaxWidth()
when (alert) {
- is AlertsComponent.AlertType.UnsupportedMethod -> SecondaryButton(
+ is AlertsComponent.AlertType.UnsupportedMethod,
+ is AlertsComponent.AlertType.RequiredAddNetwork,
+ is AlertsComponent.AlertType.RequiredReconnectWithNetwork,
+ is AlertsComponent.AlertType.TangemUnsupportedNetwork,
+ -> SecondaryButton(
modifier = buttonsModifier,
onClick = alert.onDismiss,
text = stringResourceSafe(R.string.balance_hidden_got_it_button),
@@ -105,16 +109,28 @@ private fun ButtonsContainer(alert: AlertsComponent.AlertType, modifier: Modifie
private fun AlertIcon(alert: AlertsComponent.AlertType, modifier: Modifier = Modifier) {
val color = when (alert) {
is AlertsComponent.AlertType.WcDisconnected -> TangemTheme.colors.icon.informative
- is AlertsComponent.AlertType.UnsupportedMethod -> TangemTheme.colors.icon.attention
+ is AlertsComponent.AlertType.UnsupportedMethod,
+ is AlertsComponent.AlertType.RequiredAddNetwork,
+ is AlertsComponent.AlertType.RequiredReconnectWithNetwork,
+ is AlertsComponent.AlertType.TangemUnsupportedNetwork,
+ -> TangemTheme.colors.icon.attention
}
@DrawableRes val drawableId = when (alert) {
is AlertsComponent.AlertType.WcDisconnected -> R.drawable.ic_wallet_connect_24
- is AlertsComponent.AlertType.UnsupportedMethod -> R.drawable.img_attention_20
+ is AlertsComponent.AlertType.UnsupportedMethod,
+ is AlertsComponent.AlertType.RequiredAddNetwork,
+ is AlertsComponent.AlertType.RequiredReconnectWithNetwork,
+ is AlertsComponent.AlertType.TangemUnsupportedNetwork,
+ -> R.drawable.img_attention_20
}
val iconTint = when (alert) {
is AlertsComponent.AlertType.WcDisconnected -> color
- is AlertsComponent.AlertType.UnsupportedMethod -> Color.Unspecified
+ is AlertsComponent.AlertType.UnsupportedMethod,
+ is AlertsComponent.AlertType.RequiredAddNetwork,
+ is AlertsComponent.AlertType.RequiredReconnectWithNetwork,
+ is AlertsComponent.AlertType.TangemUnsupportedNetwork,
+ -> Color.Unspecified
}
Box(
modifier = modifier
@@ -138,6 +154,9 @@ private fun AlertContentTitle(alert: AlertsComponent.AlertType, modifier: Modifi
@StringRes val titleRes: Int = when (alert) {
is AlertsComponent.AlertType.WcDisconnected -> R.string.wc_alert_session_disconnected_title
is AlertsComponent.AlertType.UnsupportedMethod -> R.string.wc_alert_unsupported_method_title
+ is AlertsComponent.AlertType.RequiredAddNetwork -> R.string.wc_alert_add_network_to_portfolio_title
+ is AlertsComponent.AlertType.RequiredReconnectWithNetwork -> R.string.wc_alert_network_not_connected_title
+ is AlertsComponent.AlertType.TangemUnsupportedNetwork -> R.string.wc_alert_unsupported_network_title
}
Text(
modifier = modifier,
@@ -157,6 +176,18 @@ private fun AlertContentDescription(alert: AlertsComponent.AlertType, modifier:
is AlertsComponent.AlertType.UnsupportedMethod -> stringResourceSafe(
R.string.wc_alert_unsupported_method_description,
)
+ is AlertsComponent.AlertType.RequiredAddNetwork -> stringResourceSafe(
+ R.string.wc_alert_unsupported_method_description,
+ alert.network,
+ )
+ is AlertsComponent.AlertType.RequiredReconnectWithNetwork -> stringResourceSafe(
+ R.string.wc_alert_network_not_connected_description,
+ alert.network,
+ )
+ is AlertsComponent.AlertType.TangemUnsupportedNetwork -> stringResourceSafe(
+ R.string.wc_alert_unsupported_network_description,
+ alert.network,
+ )
}
Text(
modifier = modifier,
@@ -188,5 +219,8 @@ private class AlertTypesProvider : CollectionPreviewParameterProvider WcInnerRoute.UnsupportedMethodAlert
HandleMethodError.UnknownSession -> WcInnerRoute.WcDappDisconnected
+
+ is HandleMethodError.NotAddedNetwork -> WcInnerRoute.RequiredAddNetwork(value.networkName)
+ is HandleMethodError.RequiredNetwork -> WcInnerRoute.RequiredReconnectWithNetwork(value.networkName)
+ is HandleMethodError.TangemUnsupportedNetwork -> WcInnerRoute.TangemUnsupportedNetwork(value.unsupportedNetwork)
}
}
\ No newline at end of file
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt
index 107e983abc..f85c7a6003 100644
--- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt
@@ -57,22 +57,27 @@ internal class WcAddNetworkModel @Inject constructor(
.onLeft { router.push(WcHandleMethodErrorConverter.convert(it)) }
.getOrNull() ?: return@launch
sendSignatureReceivedAnalytics(useCase)
- _uiState.emit(
- wcAddEthereumChainUMConverter.convert(
- WcAddEthereumChainUMConverter.Input(
- useCase = useCase,
- actions = WcTransactionActionsUM(
- onShowVerifiedAlert = ::showVerifiedAlert,
- onDismiss = { cancel(useCase) },
- onSign = { sign(useCase) },
- onCopy = { copyData(useCase.rawSdkRequest.request.params) },
- ),
- ),
- ),
- )
+ val either = useCase.invoke()
+ either
+ .onLeft { router.push(WcHandleMethodErrorConverter.convert(it)) }
+ .map { showUI() }
}
}
+ private fun showUI() {
+ _uiState.value = wcAddEthereumChainUMConverter.convert(
+ WcAddEthereumChainUMConverter.Input(
+ useCase = useCase,
+ actions = WcTransactionActionsUM(
+ onShowVerifiedAlert = ::showVerifiedAlert,
+ onDismiss = { cancel(useCase) },
+ onSign = { sign(useCase) },
+ onCopy = { copyData(useCase.rawSdkRequest.request.params) },
+ ),
+ ),
+ )
+ }
+
override fun dismiss() {
_uiState.value?.transaction?.onDismiss?.invoke() ?: router.pop()
}
diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSwitchNetworkModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSwitchNetworkModel.kt
new file mode 100644
index 0000000000..65b63ae8b6
--- /dev/null
+++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSwitchNetworkModel.kt
@@ -0,0 +1,45 @@
+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.domain.walletconnect.WcRequestUseCaseFactory
+import com.tangem.domain.walletconnect.model.HandleMethodError
+import com.tangem.domain.walletconnect.usecase.method.WcSwitchNetworkUseCase
+import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
+import com.tangem.features.walletconnect.transaction.converter.WcHandleMethodErrorConverter
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@Suppress("LongParameterList")
+@Stable
+@ModelScoped
+internal class WcSwitchNetworkModel @Inject constructor(
+ paramsContainer: ParamsContainer,
+ override val dispatchers: CoroutineDispatcherProvider,
+ private val router: Router,
+ private val useCaseFactory: WcRequestUseCaseFactory,
+) : Model() {
+
+ private val params = paramsContainer.require()
+
+ init {
+ modelScope.launch {
+ val useCase = useCaseFactory.createUseCase(params.rawRequest)
+ .onLeft { showErrorDialog(it) }
+ .getOrNull() ?: return@launch
+ val either = useCase.invoke()
+ useCase.reject()
+ either
+ .onLeft { showErrorDialog(it) }
+ .map { showErrorDialog(HandleMethodError.RequiredNetwork(it.network.name)) }
+ }
+ }
+
+ private fun showErrorDialog(error: HandleMethodError) {
+ router.push(WcHandleMethodErrorConverter.convert(error))
+ }
+}
\ No newline at end of file