Updated on 2026-08-14

This commit is contained in:
Tangem 2025-05-19 22:49:30 +07:00
parent 37ad3e6846
commit db1d205bae
8 changed files with 91 additions and 2 deletions

View file

@ -128,11 +128,13 @@ internal object WalletConnectDataModule {
sessionsManager: WcSessionsManager, sessionsManager: WcSessionsManager,
factories: WcEthNetwork.Factories, factories: WcEthNetwork.Factories,
namespaceConverter: WcEthNetwork.NamespaceConverter, namespaceConverter: WcEthNetwork.NamespaceConverter,
walletManagersFacade: WalletManagersFacade,
): WcEthNetwork = WcEthNetwork( ): WcEthNetwork = WcEthNetwork(
moshi = moshi, moshi = moshi,
namespaceConverter = namespaceConverter, namespaceConverter = namespaceConverter,
sessionsManager = sessionsManager, sessionsManager = sessionsManager,
factories = factories, factories = factories,
walletManagersFacade = walletManagersFacade,
) )
@Provides @Provides

View file

@ -0,0 +1,42 @@
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.tokens.model.Network
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.WcAddNetworkUseCase
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
internal class WcEthAddNetworkUseCase @AssistedInject constructor(
private val respondService: WcRespondService,
@Assisted val context: WcMethodUseCaseContext,
@Assisted override val method: WcEthMethod.AddEthereumChain,
) : WcAddNetworkUseCase {
override val session: WcSession
get() = context.session
override val rawSdkRequest: WcSdkSessionRequest
get() = context.rawSdkRequest
override val network: Network
get() = context.network
override val walletAddress: String
get() = context.accountAddress
override suspend fun approve(): Either<Throwable, Unit> {
return respondService.respond(rawSdkRequest, "")
}
override fun reject() {
respondService.rejectRequestNonBlock(rawSdkRequest)
}
@AssistedFactory
interface Factory {
fun create(context: WcMethodUseCaseContext, method: WcEthMethod.AddEthereumChain): WcEthAddNetworkUseCase
}
}

View file

@ -10,6 +10,7 @@ import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter.Compani
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.data.walletconnect.utils.WcNamespaceConverter import com.tangem.data.walletconnect.utils.WcNamespaceConverter
import com.tangem.domain.tokens.model.Network import com.tangem.domain.tokens.model.Network
import com.tangem.domain.walletconnect.model.WcEthAddChain
import com.tangem.domain.walletconnect.model.WcEthMethod import com.tangem.domain.walletconnect.model.WcEthMethod
import com.tangem.domain.walletconnect.model.WcEthMethodName import com.tangem.domain.walletconnect.model.WcEthMethodName
import com.tangem.domain.walletconnect.model.WcEthSignTypedDataParams import com.tangem.domain.walletconnect.model.WcEthSignTypedDataParams
@ -17,6 +18,7 @@ import com.tangem.domain.walletconnect.model.WcEthTransactionParams
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.repository.WcSessionsManager import com.tangem.domain.walletconnect.repository.WcSessionsManager
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWallet
import jakarta.inject.Inject import jakarta.inject.Inject
@ -25,6 +27,7 @@ internal class WcEthNetwork(
private val sessionsManager: WcSessionsManager, private val sessionsManager: WcSessionsManager,
private val factories: Factories, private val factories: Factories,
private val namespaceConverter: NamespaceConverter, private val namespaceConverter: NamespaceConverter,
private val walletManagersFacade: WalletManagersFacade,
) : WcRequestToUseCaseConverter { ) : WcRequestToUseCaseConverter {
override fun toWcMethodName(request: WcSdkSessionRequest): WcEthMethodName? { override fun toWcMethodName(request: WcSdkSessionRequest): WcEthMethodName? {
@ -33,16 +36,19 @@ internal class WcEthNetwork(
return name return name
} }
@Suppress("CyclomaticComplexMethod")
override suspend fun toUseCase(request: WcSdkSessionRequest): WcMethodUseCase? { override suspend fun toUseCase(request: WcSdkSessionRequest): WcMethodUseCase? {
val name = toWcMethodName(request) ?: return null val name = toWcMethodName(request) ?: return null
val method: WcEthMethod = name.toMethod(request) ?: return null
val session = sessionsManager.findSessionByTopic(request.topic) ?: return null val session = sessionsManager.findSessionByTopic(request.topic) ?: return null
val method: WcEthMethod = name.toMethod(request, session.wallet) ?: return null
val network = namespaceConverter.toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null val network = namespaceConverter.toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null
val walletManagerAddress = walletManagersFacade.getDefaultAddress(session.wallet.walletId, network).orEmpty()
val accountAddress = when (method) { val accountAddress = when (method) {
is WcEthMethod.MessageSign -> method.account is WcEthMethod.MessageSign -> method.account
is WcEthMethod.SendTransaction -> method.transaction.from is WcEthMethod.SendTransaction -> method.transaction.from
is WcEthMethod.SignTransaction -> method.transaction.from is WcEthMethod.SignTransaction -> method.transaction.from
is WcEthMethod.SignTypedData -> method.account is WcEthMethod.SignTypedData -> method.account
is WcEthMethod.AddEthereumChain -> walletManagerAddress
} }
val context = WcMethodUseCaseContext( val context = WcMethodUseCaseContext(
session = session, session = session,
@ -55,10 +61,11 @@ internal class WcEthNetwork(
is WcEthMethod.SendTransaction -> factories.sendTransaction.create(context, method) is WcEthMethod.SendTransaction -> factories.sendTransaction.create(context, method)
is WcEthMethod.SignTransaction -> factories.signTransaction.create(context, method) is WcEthMethod.SignTransaction -> factories.signTransaction.create(context, method)
is WcEthMethod.SignTypedData -> factories.signTypedData.create(context, method) is WcEthMethod.SignTypedData -> factories.signTypedData.create(context, method)
is WcEthMethod.AddEthereumChain -> factories.addNetwork.create(context, method)
} }
} }
private fun WcEthMethodName.toMethod(request: WcSdkSessionRequest): WcEthMethod? { private fun WcEthMethodName.toMethod(request: WcSdkSessionRequest, wallet: UserWallet): WcEthMethod? {
val rawParams = request.request.params val rawParams = request.request.params
return when (this) { return when (this) {
WcEthMethodName.EthSign, WcEthMethodName.EthSign,
@ -78,6 +85,13 @@ internal class WcEthNetwork(
WcEthMethod.SendTransaction(transaction = it) WcEthMethod.SendTransaction(transaction = it)
} }
} }
WcEthMethodName.AddEthereumChain -> moshi.fromJson<List<WcEthAddChain>>(rawParams)
?.firstOrNull()
?.let {
val newNetwork = namespaceConverter
.toNetwork(it.chainId, wallet) ?: return null
WcEthMethod.AddEthereumChain(rawChain = it, network = newNetwork)
}
} }
} }
@ -130,5 +144,6 @@ internal class WcEthNetwork(
val signTypedData: WcEthSignTypedDataUseCase.Factory, val signTypedData: WcEthSignTypedDataUseCase.Factory,
val sendTransaction: WcEthSendTransactionUseCase.Factory, val sendTransaction: WcEthSendTransactionUseCase.Factory,
val signTransaction: WcEthSignTransactionUseCase.Factory, val signTransaction: WcEthSignTransactionUseCase.Factory,
val addNetwork: WcEthAddNetworkUseCase.Factory,
) )
} }

View file

@ -0,0 +1,10 @@
package com.tangem.domain.walletconnect.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class WcEthAddChain(
@Json(name = "chainId")
val chainId: String,
)

View file

@ -1,5 +1,7 @@
package com.tangem.domain.walletconnect.model package com.tangem.domain.walletconnect.model
import com.tangem.domain.tokens.model.Network
sealed interface WcEthMethod : WcMethod { sealed interface WcEthMethod : WcMethod {
data class MessageSign( data class MessageSign(
@ -23,4 +25,9 @@ sealed interface WcEthMethod : WcMethod {
data class SignTransaction( data class SignTransaction(
val transaction: WcEthTransactionParams, val transaction: WcEthTransactionParams,
) : WcEthMethod ) : WcEthMethod
data class AddEthereumChain(
val rawChain: WcEthAddChain,
val network: Network,
) : WcEthMethod
} }

View file

@ -13,6 +13,7 @@ enum class WcEthMethodName(override val raw: String) : WcMethodName {
SignTypeDataV4("eth_signTypedData_v4"), SignTypeDataV4("eth_signTypedData_v4"),
SignTransaction("eth_signTransaction"), SignTransaction("eth_signTransaction"),
SendTransaction("eth_sendTransaction"), SendTransaction("eth_sendTransaction"),
AddEthereumChain("wallet_addEthereumChain"),
} }
enum class WcSolanaMethodName(override val raw: String) : WcMethodName { enum class WcSolanaMethodName(override val raw: String) : WcMethodName {

View file

@ -0,0 +1,11 @@
package com.tangem.domain.walletconnect.usecase.method
import arrow.core.Either
interface WcAddNetworkUseCase :
WcMethodUseCase,
WcMethodContext {
suspend fun approve(): Either<Throwable, Unit>
fun reject()
}

View file

@ -53,6 +53,7 @@ internal class WcRoutingModel @Inject constructor(
WcEthMethodName.SendTransaction -> TODO() WcEthMethodName.SendTransaction -> TODO()
WcSolanaMethodName.SignTransaction -> TODO() WcSolanaMethodName.SignTransaction -> TODO()
WcSolanaMethodName.SendAllTransaction -> TODO() WcSolanaMethodName.SendAllTransaction -> TODO()
WcEthMethodName.AddEthereumChain -> TODO()
is WcMethodName.Unsupported -> TODO() is WcMethodName.Unsupported -> TODO()
} }
} }