Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-29 16:40:19 +07:00
parent ecd02950fb
commit ba12a65fc8
29 changed files with 235 additions and 203 deletions

View file

@ -2,7 +2,7 @@ package com.tangem.data.walletconnect.network.ethereum
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.domain.walletconnect.model.WcEthTransactionParams
import com.tangem.domain.walletconnect.usecase.ethereum.WcEthTransaction
import com.tangem.domain.walletconnect.usecase.method.WcEthTransaction
import com.tangem.utils.converter.Converter
internal class EthTransactionParamsConverter(

View file

@ -16,8 +16,8 @@ import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.domain.transaction.usecase.SignUseCase
import com.tangem.domain.walletconnect.model.WcEthMethod
import com.tangem.domain.walletconnect.usecase.ethereum.WcEthMessageSignUseCase
import com.tangem.domain.walletconnect.usecase.sign.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletmanager.WalletManagersFacade
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -26,15 +26,15 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flow
internal class DefaultWcEthMessageSignUseCase @AssistedInject constructor(
internal class WcEthMessageSignUseCase @AssistedInject constructor(
override val respondService: WcRespondService,
@Assisted override val context: WcMethodUseCaseContext,
@Assisted private val method: WcEthMethod.MessageSign,
@Assisted override val method: WcEthMethod.MessageSign,
private val walletManagersFacade: WalletManagersFacade,
private val signUseCase: SignUseCase,
blockAidDelegate: BlockAidVerificationDelegate,
) : BaseWcSignUseCase<Nothing, WcEthMessageSignUseCase.SignModel>(),
WcEthMessageSignUseCase {
) : BaseWcSignUseCase<Nothing, WcMessageSignUseCase.SignModel>(),
WcMessageSignUseCase {
override val securityStatus = blockAidDelegate.getSecurityStatus(
network = network,
@ -44,10 +44,10 @@ internal class DefaultWcEthMessageSignUseCase @AssistedInject constructor(
accountAddress = context.accountAddress,
)
override suspend fun SignCollector<WcEthMessageSignUseCase.SignModel>.onSign(
state: WcSignState<WcEthMessageSignUseCase.SignModel>,
override suspend fun SignCollector<WcMessageSignUseCase.SignModel>.onSign(
state: WcSignState<WcMessageSignUseCase.SignModel>,
) {
val hashToSign = LegacySdkHelper.createMessageData(state.signModel.rawMsg)
val hashToSign = LegacySdkHelper.createMessageData(method.rawMessage)
val userWallet = session.wallet
val walletManager = walletManagersFacade.getOrCreateWalletManager(userWallet.walletId, network)
?: return
@ -66,18 +66,14 @@ internal class DefaultWcEthMessageSignUseCase @AssistedInject constructor(
emit(state.toResult(wcRespondResult))
}
override fun invoke(): Flow<WcSignState<WcEthMessageSignUseCase.SignModel>> = flow {
val model = WcEthMessageSignUseCase.SignModel(
rawMsg = method.message,
account = method.account,
humanMsg = LegacySdkHelper.hexToAscii(method.message).orEmpty(),
)
override fun invoke(): Flow<WcSignState<WcMessageSignUseCase.SignModel>> = flow {
val model = WcMessageSignUseCase.SignModel(humanMsg = method.humanMsg)
emitAll(delegate(model))
}
@AssistedFactory
interface Factory {
fun create(context: WcMethodUseCaseContext, method: WcEthMethod.MessageSign): DefaultWcEthMessageSignUseCase
fun create(context: WcMethodUseCaseContext, method: WcEthMethod.MessageSign): WcEthMessageSignUseCase
}
}

View file

@ -15,7 +15,7 @@ import com.tangem.domain.walletconnect.model.WcEthMethodName
import com.tangem.domain.walletconnect.model.WcEthTransactionParams
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.repository.WcSessionsManager
import com.tangem.domain.walletconnect.usecase.WcMethodUseCase
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
import com.tangem.domain.wallets.models.UserWallet
import jakarta.inject.Inject
@ -67,7 +67,8 @@ internal class WcEthNetwork(
val messageIndex = if (this == WcEthMethodName.EthSign) 1 else 0
val account = list.getOrNull(accountIndex) ?: return@let null
val message = list.getOrNull(messageIndex) ?: return@let null
WcEthMethod.MessageSign(account = account, message = message)
val humanMsg = LegacySdkHelper.hexToAscii(message).orEmpty()
WcEthMethod.MessageSign(account = account, rawMessage = message, humanMsg = humanMsg)
}
WcEthMethodName.SignTypeData -> TODO()
WcEthMethodName.SignTypeDataV4 -> TODO()
@ -106,8 +107,8 @@ internal class WcEthNetwork(
}
internal class Factories @Inject constructor(
val messageSign: DefaultWcEthMessageSignUseCase.Factory,
val sendTransaction: DefaultWcEthSendTransactionUseCase.Factory,
val signTransaction: DefaultWcEthSignTransactionUseCase.Factory,
val messageSign: WcEthMessageSignUseCase.Factory,
val sendTransaction: WcEthSendTransactionUseCase.Factory,
val signTransaction: WcEthSignTransactionUseCase.Factory,
)
}

View file

@ -11,9 +11,9 @@ import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
import com.tangem.domain.walletconnect.model.WcEthMethod
import com.tangem.domain.walletconnect.usecase.ethereum.WcEthSendTransactionUseCase
import com.tangem.domain.walletconnect.usecase.ethereum.WcEthTransaction
import com.tangem.domain.walletconnect.usecase.sign.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcEthTransaction
import com.tangem.domain.walletconnect.usecase.method.WcEthTransactionUseCase
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@ -21,14 +21,14 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flow
internal class DefaultWcEthSendTransactionUseCase @AssistedInject constructor(
internal class WcEthSendTransactionUseCase @AssistedInject constructor(
@Assisted override val context: WcMethodUseCaseContext,
@Assisted private val method: WcEthMethod.SendTransaction,
@Assisted override val method: WcEthMethod.SendTransaction,
override val respondService: WcRespondService,
private val sendTransaction: SendTransactionUseCase,
blockAidDelegate: BlockAidVerificationDelegate,
) : BaseWcSignUseCase<Fee, WcEthTransaction>(),
WcEthSendTransactionUseCase {
WcEthTransactionUseCase {
override val securityStatus = blockAidDelegate.getSecurityStatus(
network = network,
@ -62,9 +62,6 @@ internal class DefaultWcEthSendTransactionUseCase @AssistedInject constructor(
@AssistedFactory
interface Factory {
fun create(
context: WcMethodUseCaseContext,
method: WcEthMethod.SendTransaction,
): DefaultWcEthSendTransactionUseCase
fun create(context: WcMethodUseCaseContext, method: WcEthMethod.SendTransaction): WcEthSendTransactionUseCase
}
}

View file

@ -12,9 +12,9 @@ import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.domain.transaction.usecase.PrepareForSendUseCase
import com.tangem.domain.walletconnect.model.WcEthMethod
import com.tangem.domain.walletconnect.usecase.ethereum.WcEthSignTransactionUseCase
import com.tangem.domain.walletconnect.usecase.ethereum.WcEthTransaction
import com.tangem.domain.walletconnect.usecase.sign.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcEthTransaction
import com.tangem.domain.walletconnect.usecase.method.WcEthTransactionUseCase
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@ -23,14 +23,14 @@ import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flow
internal class DefaultWcEthSignTransactionUseCase @AssistedInject constructor(
internal class WcEthSignTransactionUseCase @AssistedInject constructor(
override val respondService: WcRespondService,
private val prepareForSend: PrepareForSendUseCase,
@Assisted override val context: WcMethodUseCaseContext,
@Assisted private val method: WcEthMethod.SignTransaction,
@Assisted override val method: WcEthMethod.SignTransaction,
blockAidDelegate: BlockAidVerificationDelegate,
) : BaseWcSignUseCase<Fee, WcEthTransaction>(),
WcEthSignTransactionUseCase {
WcEthTransactionUseCase {
override val securityStatus = blockAidDelegate.getSecurityStatus(
network = network,
@ -71,9 +71,6 @@ internal class DefaultWcEthSignTransactionUseCase @AssistedInject constructor(
@AssistedFactory
interface Factory {
fun create(
context: WcMethodUseCaseContext,
method: WcEthMethod.SignTransaction,
): DefaultWcEthSignTransactionUseCase
fun create(context: WcMethodUseCaseContext, method: WcEthMethod.SignTransaction): WcEthSignTransactionUseCase
}
}

View file

@ -11,7 +11,7 @@ import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
import com.tangem.domain.transaction.usecase.PrepareForSendUseCase
import com.tangem.domain.walletconnect.model.WcSolanaMethod
import com.tangem.domain.walletconnect.usecase.sign.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.solana.WcSolanaSignAllTransactionUseCase
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -25,7 +25,7 @@ internal class DefaultWcSolanaSignAllTransactionUseCase @AssistedInject construc
override val respondService: WcRespondService,
private val prepareForSend: PrepareForSendUseCase,
@Assisted override val context: WcMethodUseCaseContext,
@Assisted private val method: WcSolanaMethod.SignAllTransaction,
@Assisted override val method: WcSolanaMethod.SignAllTransaction,
blockAidDelegate: BlockAidVerificationDelegate,
) : BaseWcSignUseCase<Nothing, List<TransactionData.Compiled>>(),
WcSolanaSignAllTransactionUseCase {

View file

@ -11,7 +11,7 @@ import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
import com.tangem.domain.transaction.usecase.PrepareForSendUseCase
import com.tangem.domain.walletconnect.model.WcSolanaMethod
import com.tangem.domain.walletconnect.usecase.sign.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.solana.WcSolanaSignTransactionUseCase
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -23,7 +23,7 @@ internal class DefaultWcSolanaSignTransactionUseCase @AssistedInject constructor
override val respondService: WcRespondService,
private val prepareForSend: PrepareForSendUseCase,
@Assisted override val context: WcMethodUseCaseContext,
@Assisted private val method: WcSolanaMethod.SignTransaction,
@Assisted override val method: WcSolanaMethod.SignTransaction,
blockAidDelegate: BlockAidVerificationDelegate,
) : BaseWcSignUseCase<Nothing, TransactionData.Compiled>(),
WcSolanaSignTransactionUseCase {

View file

@ -0,0 +1,58 @@
package com.tangem.data.walletconnect.network.solana
import arrow.core.left
import com.domain.blockaid.models.transaction.CheckTransactionResult
import com.tangem.blockchain.extensions.decodeBase58
import com.tangem.blockchain.extensions.encodeBase58
import com.tangem.data.walletconnect.respond.WcRespondService
import com.tangem.data.walletconnect.sign.BaseWcSignUseCase
import com.tangem.data.walletconnect.sign.SignCollector
import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.domain.core.lce.LceFlow
import com.tangem.domain.transaction.usecase.SignUseCase
import com.tangem.domain.walletconnect.model.WcSolanaMethod
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
internal class WcSolanaMessageSignUseCase @AssistedInject constructor(
@Assisted override val context: WcMethodUseCaseContext,
@Assisted override val method: WcSolanaMethod.SignMessage,
private val signUseCase: SignUseCase,
override val respondService: WcRespondService,
) : BaseWcSignUseCase<Nothing, WcMessageSignUseCase.SignModel>(),
WcMessageSignUseCase {
override val securityStatus: LceFlow<Throwable, CheckTransactionResult> =
emptyFlow() // BlockAid doesn't support solana_signMessage
override suspend fun SignCollector<WcMessageSignUseCase.SignModel>.onSign(
state: WcSignState<WcMessageSignUseCase.SignModel>,
) {
val hashToSign = method.rawMessage.decodeBase58() ?: byteArrayOf()
val userWallet = session.wallet
val signedHash = signUseCase(hashToSign, userWallet, network)
.onLeft { emit(state.toResult(it.left())) }
.getOrNull() ?: return
val respond = "{ signature: \"${signedHash.encodeBase58()}\" }"
val wcRespondResult = respondService.respond(rawSdkRequest, respond)
emit(state.toResult(wcRespondResult))
}
override fun invoke(): Flow<WcSignState<WcMessageSignUseCase.SignModel>> {
return delegate.invoke(initModel = WcMessageSignUseCase.SignModel(method.humanMsg))
}
@AssistedFactory
interface Factory {
fun create(context: WcMethodUseCaseContext, method: WcSolanaMethod.SignMessage): WcSolanaMessageSignUseCase
}
}

View file

@ -2,7 +2,9 @@ package com.tangem.data.walletconnect.network.solana
import com.squareup.moshi.Moshi
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.extensions.decodeBase58
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
import com.tangem.common.extensions.toHexString
import com.tangem.data.walletconnect.model.CAIP2
import com.tangem.data.walletconnect.model.NamespaceKey
import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter
@ -14,7 +16,7 @@ import com.tangem.domain.walletconnect.model.WcSolanaMethod
import com.tangem.domain.walletconnect.model.WcSolanaMethodName
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.repository.WcSessionsManager
import com.tangem.domain.walletconnect.usecase.WcMethodUseCase
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.lib.crypto.UserWalletManager
import jakarta.inject.Inject
@ -46,10 +48,10 @@ internal class WcSolanaNetwork(
session = session,
rawSdkRequest = request,
network = network,
accountAddress = accountAddress,
accountAddress = accountAddress.orEmpty(),
)
return when (method) {
is WcSolanaMethod.SignMessage -> TODO()
is WcSolanaMethod.SignMessage -> factories.messageSign.create(context, method)
is WcSolanaMethod.SignTransaction -> factories.signTransaction.create(context, method)
is WcSolanaMethod.SignAllTransaction -> factories.signAllTransaction.create(context, method)
}
@ -95,7 +97,12 @@ internal class WcSolanaNetwork(
val rawParams = request.request.params
return when (this) {
WcSolanaMethodName.SignMessage -> moshi.fromJson<WcSolanaSignMessageRequest>(rawParams)?.let { request ->
WcSolanaMethod.SignMessage(pubKey = request.publicKey, message = request.message)
val humanMsg = request.message.decodeBase58()?.toHexString().orEmpty()
WcSolanaMethod.SignMessage(
pubKey = request.publicKey,
rawMessage = request.message,
humanMsg = humanMsg,
)
}
WcSolanaMethodName.SignTransaction -> moshi.fromJson<WcSolanaSignTransactionRequest>(rawParams)
?.let { request -> WcSolanaMethod.SignTransaction(request.transaction) }
@ -106,6 +113,7 @@ internal class WcSolanaNetwork(
}
internal class Factories @Inject constructor(
val messageSign: WcSolanaMessageSignUseCase.Factory,
val signTransaction: DefaultWcSolanaSignTransactionUseCase.Factory,
val signAllTransaction: DefaultWcSolanaSignAllTransactionUseCase.Factory,
)

View file

@ -58,10 +58,10 @@ internal class AssociateNetworksDelegate constructor(
val wcNetwork = namespaceConverters.firstNotNullOfOrNull { it.toNetwork(chainId, wallet) }
?: return@forEach
val walletNetwork = walletNetworks.find { network -> wcNetwork.id == network.id }
if (walletNetwork == null) {
available.add(wcNetwork)
if (walletNetwork != null) {
available.add(walletNetwork)
} else {
notAdded.add(walletNetwork)
notAdded.add(wcNetwork)
}
}
if (unknownRequired.isNotEmpty()) throw WcPairError.UnsupportedNetworks(unknownRequired)

View file

@ -2,7 +2,7 @@ package com.tangem.data.walletconnect.request
import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.usecase.WcMethodUseCase
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
import javax.inject.Inject
internal class DefaultWcRequestUseCaseFactory @Inject constructor(

View file

@ -4,7 +4,7 @@ import com.squareup.moshi.Moshi
import com.squareup.moshi.adapter
import com.tangem.domain.walletconnect.model.WcMethodName
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.usecase.WcMethodUseCase
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
interface WcRequestToUseCaseConverter {
fun toWcMethodName(request: WcSdkSessionRequest): WcMethodName?

View file

@ -21,10 +21,8 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import timber.log.Timber
import kotlin.coroutines.resume
import kotlin.time.Duration.Companion.seconds
internal class DefaultWcSessionsManager(
private val store: WalletConnectStore,
@ -67,19 +65,8 @@ internal class DefaultWcSessionsManager(
override suspend fun removeSession(session: WcSession): Either<Throwable, Unit> {
val topic = session.sdkModel.topic
val sdkCall = sdkDisconnectSession(topic)
sdkCall.onLeft { return it.left() }
suspend fun waitSdkCallback() = onSessionDelete.receiveAsFlow().first {
val isSomeError = it is Wallet.Model.SessionDelete.Error
val isDeleted = it is Wallet.Model.SessionDelete.Success && it.topic == topic
isSomeError || isDeleted
}
val waitSdkCallback = runCatching { withTimeout(10.seconds) { waitSdkCallback() } }
val sdkCallback = waitSdkCallback.getOrElse { return it.left() }
return when (sdkCallback) {
is Wallet.Model.SessionDelete.Error -> sdkCallback.error.left()
is Wallet.Model.SessionDelete.Success -> Unit.right()
}
.onRight { onSessionDelete.trySend(Wallet.Model.SessionDelete.Success(topic = topic, reason = "")) }
return sdkCall
}
override suspend fun findSessionByTopic(topic: String): WcSession? = withContext(dispatchers.io) {

View file

@ -4,10 +4,9 @@ import com.tangem.data.walletconnect.respond.WcRespondService
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.walletconnect.model.WcSession
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.usecase.WcMethodUseCase
import com.tangem.domain.walletconnect.usecase.sign.WcSignState
import com.tangem.domain.walletconnect.usecase.sign.WcSignUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase
import kotlinx.coroutines.flow.FlowCollector
internal abstract class BaseWcSignUseCase<MiddleAction, SignModel> :
@ -21,8 +20,8 @@ internal abstract class BaseWcSignUseCase<MiddleAction, SignModel> :
abstract val context: WcMethodUseCaseContext
override val network: Network get() = context.network
override val session: WcSession get() = context.session
override val walletAddress: String get() = context.accountAddress
override val rawSdkRequest: WcSdkSessionRequest get() = context.rawSdkRequest
val wallet: UserWallet get() = session.wallet
protected val delegate by lazy {
WcSignUseCaseDelegate(
@ -60,7 +59,7 @@ internal class WcMethodUseCaseContext(
val session: WcSession,
val rawSdkRequest: WcSdkSessionRequest,
val network: Network,
val accountAddress: String?,
val accountAddress: String,
)
internal typealias SignCollector<SignModel> = FlowCollector<WcSignState<SignModel>>

View file

@ -1,8 +1,8 @@
package com.tangem.data.walletconnect.sign
import arrow.core.Either
import com.tangem.domain.walletconnect.usecase.sign.WcSignState
import com.tangem.domain.walletconnect.usecase.sign.WcSignStep
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
object SignStateConverter {

View file

@ -4,8 +4,8 @@ import arrow.core.left
import com.tangem.data.walletconnect.sign.SignStateConverter.toPreSign
import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
import com.tangem.data.walletconnect.sign.SignStateConverter.toSigning
import com.tangem.domain.walletconnect.usecase.sign.WcSignState
import com.tangem.domain.walletconnect.usecase.sign.WcSignStep
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.awaitClose

View file

@ -9,8 +9,8 @@ import com.tangem.data.walletconnect.sign.SignCollector
import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
import com.tangem.data.walletconnect.sign.SignStateConverter.toSigning
import com.tangem.data.walletconnect.sign.WcSignUseCaseDelegate
import com.tangem.domain.walletconnect.usecase.sign.WcSignState
import com.tangem.domain.walletconnect.usecase.sign.WcSignStep
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
import junit.framework.TestCase.assertEquals
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.FlowCollector

View file

@ -3,8 +3,9 @@ package com.tangem.domain.walletconnect.model
sealed interface WcEthMethod : WcMethod {
data class MessageSign(
val message: String,
val rawMessage: String,
val account: String,
val humanMsg: String,
) : WcEthMethod
data class SendTransaction(

View file

@ -4,7 +4,8 @@ sealed interface WcSolanaMethod : WcMethod {
data class SignMessage(
val pubKey: String,
val message: String,
val rawMessage: String,
val humanMsg: String,
) : WcSolanaMethod
data class SignTransaction(

View file

@ -1,7 +1,7 @@
package com.tangem.domain.walletconnect
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.usecase.WcMethodUseCase
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
interface WcRequestUseCaseFactory {

View file

@ -1,18 +0,0 @@
package com.tangem.domain.walletconnect.usecase
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.walletconnect.model.WcSession
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
interface WcUseCase
interface WcMethodUseCase : WcUseCase {
val session: WcSession
val rawSdkRequest: WcSdkSessionRequest
val network: Network
}
interface WcMutableFee {
fun updateFee(fee: Fee)
}

View file

@ -1,7 +0,0 @@
package com.tangem.domain.walletconnect.usecase
import kotlinx.coroutines.flow.Flow
interface WcUseCasesFlowProvider {
val useCases: Flow<WcUseCase>
}

View file

@ -1,16 +0,0 @@
package com.tangem.domain.walletconnect.usecase.ethereum
import com.tangem.domain.walletconnect.usecase.blockaid.WcBlockAidEligibleTransactionUseCase
import com.tangem.domain.walletconnect.usecase.sign.WcSignUseCase
interface WcEthMessageSignUseCase :
WcSignUseCase,
WcSignUseCase.SimpleRun<WcEthMessageSignUseCase.SignModel>,
WcBlockAidEligibleTransactionUseCase {
data class SignModel(
val humanMsg: String,
val account: String,
val rawMsg: String,
)
}

View file

@ -1,45 +0,0 @@
package com.tangem.domain.walletconnect.usecase.ethereum
import com.tangem.blockchain.common.TransactionData
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.walletconnect.model.WcSession
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.usecase.WcMutableFee
import com.tangem.domain.walletconnect.usecase.blockaid.WcBlockAidEligibleTransactionUseCase
import com.tangem.domain.walletconnect.usecase.sign.WcSignUseCase
interface WcEthSendTransactionUseCase :
WcSignUseCase,
WcSignUseCase.SimpleRun<WcEthTransaction>,
WcBlockAidEligibleTransactionUseCase,
WcMutableFee {
override val session: WcSession
override val rawSdkRequest: WcSdkSessionRequest
override val network: Network
override fun sign()
override fun cancel()
override fun updateFee(fee: Fee)
}
interface WcEthSignTransactionUseCase :
WcSignUseCase,
WcSignUseCase.SimpleRun<WcEthTransaction>,
WcBlockAidEligibleTransactionUseCase,
WcMutableFee {
override val session: WcSession
override val rawSdkRequest: WcSdkSessionRequest
override val network: Network
override fun sign()
override fun cancel()
override fun updateFee(fee: Fee)
}
data class WcEthTransaction(
val dAppFee: Fee.Ethereum.Legacy?,
val transactionData: TransactionData.Uncompiled,
)

View file

@ -0,0 +1,22 @@
package com.tangem.domain.walletconnect.usecase.method
import com.tangem.blockchain.common.TransactionData
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.domain.walletconnect.usecase.blockaid.WcBlockAidEligibleTransactionUseCase
/**
* UseCase for
* ## Ethereum
* eth_sendTransaction https://docs.reown.com/advanced/multichain/rpc-reference/ethereum-rpc#eth-sendtransaction
* eth_signTransaction https://docs.reown.com/advanced/multichain/rpc-reference/ethereum-rpc#eth-signtransaction
*/
interface WcEthTransactionUseCase :
WcSignUseCase,
WcSignUseCase.SimpleRun<WcEthTransaction>,
WcBlockAidEligibleTransactionUseCase,
WcMutableFee
data class WcEthTransaction(
val dAppFee: Fee.Ethereum.Legacy?,
val transactionData: TransactionData.Uncompiled,
)

View file

@ -0,0 +1,24 @@
package com.tangem.domain.walletconnect.usecase.method
import com.tangem.domain.walletconnect.usecase.blockaid.WcBlockAidEligibleTransactionUseCase
/**
* UseCase for
*
* ## Ethereum
* personal_sign https://docs.reown.com/advanced/multichain/rpc-reference/ethereum-rpc#personal-sign
* eth_sign https://docs.reown.com/advanced/multichain/rpc-reference/ethereum-rpc#eth-sign
* todo() eth_signTypedData https://docs.reown.com/advanced/multichain/rpc-reference/ethereum-rpc#eth-signtypeddata
*
* ## Solana
* solana_signMessage https://docs.reown.com/advanced/multichain/rpc-reference/solana-rpc#solana-signmessage
*/
interface WcMessageSignUseCase :
WcSignUseCase,
WcSignUseCase.SimpleRun<WcMessageSignUseCase.SignModel>,
WcBlockAidEligibleTransactionUseCase {
data class SignModel(
val humanMsg: String,
)
}

View file

@ -0,0 +1,57 @@
package com.tangem.domain.walletconnect.usecase.method
import arrow.core.Either
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.walletconnect.model.WcMethod
import com.tangem.domain.walletconnect.model.WcSession
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.wallets.models.UserWallet
import kotlinx.coroutines.flow.Flow
interface WcMethodUseCase : WcMethodContext
interface WcMethodContext {
val session: WcSession
val rawSdkRequest: WcSdkSessionRequest
val network: Network
val method: WcMethod
val walletAddress: String
val wallet: UserWallet get() = session.wallet
}
/**
* Wc Methods that support an updatable fee
*/
interface WcMutableFee {
fun updateFee(fee: Fee)
}
/**
* Wc Methods that must be signed by Tangem card
* [WcSignState] represents signing state
*/
interface WcSignUseCase : WcMethodContext {
fun cancel()
fun sign()
interface SimpleRun<SignModel> {
operator fun invoke(): Flow<WcSignState<SignModel>>
}
interface ArgsRun<SignModel, Args> {
operator fun invoke(args: Args): Flow<WcSignState<SignModel>>
}
}
data class WcSignState<SignModel>(
val signModel: SignModel,
val domainStep: WcSignStep,
)
sealed interface WcSignStep {
data object PreSign : WcSignStep
data object Signing : WcSignStep
data class Result(val result: Either<Throwable, Unit>) : WcSignStep
}

View file

@ -1,30 +0,0 @@
package com.tangem.domain.walletconnect.usecase.sign
import arrow.core.Either
import com.tangem.domain.walletconnect.usecase.WcMethodUseCase
import kotlinx.coroutines.flow.Flow
interface WcSignUseCase : WcMethodUseCase {
fun cancel()
fun sign()
interface SimpleRun<SignModel> {
operator fun invoke(): Flow<WcSignState<SignModel>>
}
interface ArgsRun<SignModel, Args> {
operator fun invoke(args: Args): Flow<WcSignState<SignModel>>
}
}
data class WcSignState<SignModel>(
val signModel: SignModel,
val domainStep: WcSignStep,
)
sealed interface WcSignStep {
data object PreSign : WcSignStep
data object Signing : WcSignStep
data class Result(val result: Either<Throwable, Unit>) : WcSignStep
}

View file

@ -5,8 +5,8 @@ import com.tangem.domain.tokens.model.Network
import com.tangem.domain.walletconnect.model.WcSession
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.usecase.blockaid.WcBlockAidEligibleTransactionUseCase
import com.tangem.domain.walletconnect.usecase.sign.WcSignState
import com.tangem.domain.walletconnect.usecase.sign.WcSignUseCase
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase
import kotlinx.coroutines.flow.Flow
interface WcSolanaSignTransactionUseCase :