Updated on 2026-08-14
This commit is contained in:
parent
c470e8ef27
commit
2b12514ee1
24 changed files with 381 additions and 48 deletions
|
|
@ -30,6 +30,7 @@ dependencies {
|
|||
|
||||
/* Project - Core */
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.core.analytics)
|
||||
|
||||
/* DI */
|
||||
implementation(deps.hilt.core)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.data.walletconnect.di
|
|||
import android.app.Application
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.DefaultWalletConnectRepository
|
||||
import com.tangem.data.walletconnect.initialize.DefaultWcInitializeUseCase
|
||||
import com.tangem.data.walletconnect.network.ethereum.WcEthNetwork
|
||||
|
|
@ -213,8 +214,11 @@ internal object WalletConnectDataModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesWcDisconnectUseCase(sessionsManager: WcSessionsManager): WcDisconnectUseCase {
|
||||
return WcDisconnectUseCase(sessionsManager)
|
||||
fun providesWcDisconnectUseCase(
|
||||
sessionsManager: WcSessionsManager,
|
||||
analytics: AnalyticsEventHandler,
|
||||
): WcDisconnectUseCase {
|
||||
return WcDisconnectUseCase(sessionsManager, analytics)
|
||||
}
|
||||
|
||||
internal class DiHelperBox(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.data.walletconnect.pair.WcPairSdkDelegate
|
|||
import com.tangem.data.walletconnect.request.DefaultWcRequestService
|
||||
import com.tangem.data.walletconnect.sessions.DefaultWcSessionsManager
|
||||
import com.tangem.data.walletconnect.utils.WcSdkObserver
|
||||
import com.tangem.data.walletconnect.utils.WC_TAG
|
||||
import com.tangem.domain.walletconnect.usecase.initialize.WcInitializeUseCase
|
||||
import timber.log.Timber
|
||||
|
||||
|
|
@ -56,6 +57,7 @@ internal class DefaultWcInitializeUseCase(
|
|||
val walletDelegate = defineWalletDelegate()
|
||||
WalletKit.setWalletDelegate(walletDelegate)
|
||||
wcSdkObservers.forEach { it.onWcSdkInit() }
|
||||
Timber.tag(WC_TAG).i("onWcSdkInit")
|
||||
},
|
||||
onError = { error ->
|
||||
Timber.e("Error while initializing Web3Wallet: $error")
|
||||
|
|
@ -68,26 +70,32 @@ internal class DefaultWcInitializeUseCase(
|
|||
get() = super.onSessionAuthenticate
|
||||
|
||||
override fun onConnectionStateChange(state: Wallet.Model.ConnectionState) {
|
||||
Timber.tag(WC_TAG).i("sdk callback onConnectionStateChange isAvailable=${state.isAvailable}")
|
||||
wcSdkObservers.forEach { it.onConnectionStateChange(state) }
|
||||
}
|
||||
|
||||
override fun onError(error: Wallet.Model.Error) {
|
||||
Timber.tag(WC_TAG).e(error.throwable, "sdk callback onError")
|
||||
wcSdkObservers.forEach { it.onError(error) }
|
||||
}
|
||||
|
||||
override fun onProposalExpired(proposal: Wallet.Model.ExpiredProposal) {
|
||||
Timber.tag(WC_TAG).i("sdk callback onProposalExpired $proposal")
|
||||
wcSdkObservers.forEach { it.onProposalExpired(proposal) }
|
||||
}
|
||||
|
||||
override fun onRequestExpired(request: Wallet.Model.ExpiredRequest) {
|
||||
Timber.tag(WC_TAG).i("sdk callback onRequestExpired $request")
|
||||
wcSdkObservers.forEach { it.onRequestExpired(request) }
|
||||
}
|
||||
|
||||
override fun onSessionDelete(sessionDelete: Wallet.Model.SessionDelete) {
|
||||
Timber.tag(WC_TAG).i("sdk callback onSessionDelete $sessionDelete")
|
||||
wcSdkObservers.forEach { it.onSessionDelete(sessionDelete) }
|
||||
}
|
||||
|
||||
override fun onSessionExtend(session: Wallet.Model.Session) {
|
||||
Timber.tag(WC_TAG).i("sdk callback onSessionExtend $session")
|
||||
wcSdkObservers.forEach { it.onSessionExtend(session) }
|
||||
}
|
||||
|
||||
|
|
@ -95,6 +103,7 @@ internal class DefaultWcInitializeUseCase(
|
|||
sessionProposal: Wallet.Model.SessionProposal,
|
||||
verifyContext: Wallet.Model.VerifyContext,
|
||||
) {
|
||||
Timber.tag(WC_TAG).i("sdk callback onSessionProposal $sessionProposal")
|
||||
wcSdkObservers.forEach { it.onSessionProposal(sessionProposal, verifyContext) }
|
||||
}
|
||||
|
||||
|
|
@ -102,14 +111,17 @@ internal class DefaultWcInitializeUseCase(
|
|||
sessionRequest: Wallet.Model.SessionRequest,
|
||||
verifyContext: Wallet.Model.VerifyContext,
|
||||
) {
|
||||
Timber.tag(WC_TAG).i("sdk callback onSessionRequest $sessionRequest")
|
||||
wcSdkObservers.forEach { it.onSessionRequest(sessionRequest, verifyContext) }
|
||||
}
|
||||
|
||||
override fun onSessionSettleResponse(settleSessionResponse: Wallet.Model.SettledSessionResponse) {
|
||||
Timber.tag(WC_TAG).i("sdk callback onSessionSettleResponse $settleSessionResponse")
|
||||
wcSdkObservers.forEach { it.onSessionSettleResponse(settleSessionResponse) }
|
||||
}
|
||||
|
||||
override fun onSessionUpdateResponse(sessionUpdateResponse: Wallet.Model.SessionUpdateResponse) {
|
||||
Timber.tag(WC_TAG).i("sdk callback onSessionUpdateResponse $sessionUpdateResponse")
|
||||
wcSdkObservers.forEach { it.onSessionUpdateResponse(sessionUpdateResponse) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.tangem.blockchain.extensions.isAscii
|
|||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.common.extensions.toDecompressedPublicKey
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.network.ethereum.LegacySdkHelper.prepareToSendMessageData
|
||||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.data.walletconnect.sign.BaseWcSignUseCase
|
||||
|
|
@ -28,8 +29,10 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class WcEthMessageSignUseCase @AssistedInject constructor(
|
||||
override val respondService: WcRespondService,
|
||||
override val analytics: AnalyticsEventHandler,
|
||||
@Assisted override val context: WcMethodUseCaseContext,
|
||||
@Assisted override val method: WcEthMethod.MessageSign,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.data.walletconnect.network.ethereum
|
|||
import arrow.core.left
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.extensions.formatHex
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
|
||||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.data.walletconnect.sign.BaseWcSignUseCase
|
||||
|
|
@ -25,6 +26,7 @@ internal class WcEthSendTransactionUseCase @AssistedInject constructor(
|
|||
@Assisted override val context: WcMethodUseCaseContext,
|
||||
@Assisted override val method: WcEthMethod.SendTransaction,
|
||||
override val respondService: WcRespondService,
|
||||
override val analytics: AnalyticsEventHandler,
|
||||
private val sendTransaction: SendTransactionUseCase,
|
||||
blockAidDelegate: BlockAidVerificationDelegate,
|
||||
) : BaseWcSignUseCase<Fee, WcEthTransaction>(),
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import arrow.core.left
|
|||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.extensions.formatHex
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
|
||||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.data.walletconnect.sign.BaseWcSignUseCase
|
||||
|
|
@ -25,6 +26,7 @@ import kotlinx.coroutines.flow.flow
|
|||
|
||||
internal class WcEthSignTransactionUseCase @AssistedInject constructor(
|
||||
override val respondService: WcRespondService,
|
||||
override val analytics: AnalyticsEventHandler,
|
||||
private val prepareForSend: PrepareForSendUseCase,
|
||||
@Assisted override val context: WcMethodUseCaseContext,
|
||||
@Assisted override val method: WcEthMethod.SignTransaction,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.data.walletconnect.network.ethereum
|
|||
|
||||
import arrow.core.left
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumUtils
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.network.ethereum.LegacySdkHelper.prepareToSendMessageData
|
||||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.data.walletconnect.sign.BaseWcSignUseCase
|
||||
|
|
@ -21,8 +22,10 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class WcEthSignTypedDataUseCase @AssistedInject constructor(
|
||||
override val respondService: WcRespondService,
|
||||
override val analytics: AnalyticsEventHandler,
|
||||
@Assisted override val context: WcMethodUseCaseContext,
|
||||
@Assisted override val method: WcEthMethod.SignTypedData,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.data.walletconnect.network.solana
|
|||
import arrow.core.left
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.extensions.encodeBase64
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.data.walletconnect.sign.BaseWcSignUseCase
|
||||
import com.tangem.data.walletconnect.sign.SignCollector
|
||||
|
|
@ -23,6 +24,7 @@ import org.json.JSONObject
|
|||
|
||||
internal class DefaultWcSolanaSignAllTransactionUseCase @AssistedInject constructor(
|
||||
override val respondService: WcRespondService,
|
||||
override val analytics: AnalyticsEventHandler,
|
||||
private val prepareForSend: PrepareForSendUseCase,
|
||||
@Assisted override val context: WcMethodUseCaseContext,
|
||||
@Assisted override val method: WcSolanaMethod.SignAllTransaction,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.data.walletconnect.network.solana
|
|||
import arrow.core.left
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.extensions.encodeBase58
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.data.walletconnect.sign.BaseWcSignUseCase
|
||||
import com.tangem.data.walletconnect.sign.SignCollector
|
||||
|
|
@ -21,6 +22,7 @@ import okio.ByteString.Companion.decodeBase64
|
|||
|
||||
internal class DefaultWcSolanaSignTransactionUseCase @AssistedInject constructor(
|
||||
override val respondService: WcRespondService,
|
||||
override val analytics: AnalyticsEventHandler,
|
||||
private val prepareForSend: PrepareForSendUseCase,
|
||||
@Assisted override val context: WcMethodUseCaseContext,
|
||||
@Assisted override val method: WcSolanaMethod.SignTransaction,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ 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.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.data.walletconnect.sign.BaseWcSignUseCase
|
||||
import com.tangem.data.walletconnect.sign.SignCollector
|
||||
|
|
@ -25,6 +26,7 @@ internal class WcSolanaMessageSignUseCase @AssistedInject constructor(
|
|||
@Assisted override val method: WcSolanaMethod.SignMessage,
|
||||
private val signUseCase: SignUseCase,
|
||||
override val respondService: WcRespondService,
|
||||
override val analytics: AnalyticsEventHandler,
|
||||
) : BaseWcSignUseCase<Nothing, WcMessageSignUseCase.SignModel>(),
|
||||
WcMessageSignUseCase {
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ import arrow.core.right
|
|||
import com.domain.blockaid.models.dapp.CheckDAppResult
|
||||
import com.domain.blockaid.models.dapp.DAppData
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.walletconnect.WcAnalyticEvents
|
||||
import com.tangem.data.walletconnect.utils.WC_TAG
|
||||
import com.tangem.data.walletconnect.utils.WcSdkSessionConverter
|
||||
import com.tangem.domain.blockaid.BlockAidVerifier
|
||||
import com.tangem.domain.walletconnect.model.*
|
||||
|
|
@ -18,20 +21,19 @@ import dagger.assisted.Assisted
|
|||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.flow.*
|
||||
import timber.log.Timber
|
||||
|
||||
val unsupportedDApps = listOf("dYdX", "dYdX v4", "Apex Pro", "The Sandbox")
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class DefaultWcPairUseCase @AssistedInject constructor(
|
||||
private val sessionsManager: WcSessionsManager,
|
||||
private val associateNetworksDelegate: AssociateNetworksDelegate,
|
||||
private val caipNamespaceDelegate: CaipNamespaceDelegate,
|
||||
private val sdkDelegate: WcPairSdkDelegate,
|
||||
private val blockAidVerifier: BlockAidVerifier,
|
||||
private val analytics: AnalyticsEventHandler,
|
||||
@Assisted private val pairRequest: WcPairRequest,
|
||||
) : WcPairUseCase {
|
||||
|
||||
|
|
@ -40,26 +42,35 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
override operator fun invoke(): Flow<WcPairState> {
|
||||
val (uri: String, source: WcPairRequest.Source) = pairRequest
|
||||
return flow {
|
||||
Timber.tag(WC_TAG).i("start pair flow $pairRequest")
|
||||
analytics.send(WcAnalyticEvents.NewPairInitiated(source))
|
||||
emit(WcPairState.Loading)
|
||||
|
||||
val sdkSessionProposal = sdkDelegate.pair(uri)
|
||||
.onLeft { emit(WcPairState.Error(it)) }
|
||||
.onLeft {
|
||||
Timber.tag(WC_TAG).e(it, "Failed to call pair $pairRequest")
|
||||
emit(WcPairState.Error(it))
|
||||
}
|
||||
.getOrNull() ?: return@flow
|
||||
|
||||
// check unsupported dApps, just local constant for now, finish if unsupported
|
||||
if (sdkSessionProposal.name in unsupportedDApps) {
|
||||
Timber.i("Unsupported DApp")
|
||||
Timber.tag(WC_TAG).i("Unsupported DApp ${sdkSessionProposal.name}")
|
||||
val error = WcPairState.Error(WcPairError.UnsupportedDApp)
|
||||
emit(error)
|
||||
return@flow
|
||||
}
|
||||
|
||||
val proposalState = buildProposalState(sdkSessionProposal)
|
||||
.onLeft { emit(WcPairState.Error(it)) }
|
||||
.onLeft {
|
||||
analytics.send(WcAnalyticEvents.PairFailed)
|
||||
emit(WcPairState.Error(it))
|
||||
}
|
||||
.getOrNull() ?: return@flow
|
||||
emit(proposalState)
|
||||
|
||||
// wait first terminal action and continue WC pair flow
|
||||
Timber.tag(WC_TAG).i("pair wait terminal action ${sdkSessionProposal.name}")
|
||||
val terminalAction = onCallTerminalAction.receiveAsFlow().first()
|
||||
val sessionForApprove: WcSessionApprove? = when (terminalAction) {
|
||||
is TerminalAction.Approve -> terminalAction.sessionForApprove
|
||||
|
|
@ -67,6 +78,7 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
}
|
||||
// finish flow if rejected above
|
||||
if (sessionForApprove == null) {
|
||||
analytics.send(WcAnalyticEvents.SessionDisconnected(proposalState.dAppSession))
|
||||
sdkDelegate.rejectSession(sdkSessionProposal.proposerPublicKey)
|
||||
return@flow
|
||||
}
|
||||
|
|
@ -84,17 +96,34 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
networks = sessionForApprove.network.toSet(),
|
||||
)
|
||||
sessionsManager.saveSession(newSession)
|
||||
analytics.send(
|
||||
WcAnalyticEvents.DAppConnected(
|
||||
proposalState.dAppSession,
|
||||
sessionForApprove,
|
||||
),
|
||||
)
|
||||
newSession
|
||||
}.onLeft {
|
||||
analytics.send(WcAnalyticEvents.DAppConnectionFailed(it.message))
|
||||
Timber.tag(WC_TAG).e(it, "Failed to approve session ${sdkSessionProposal.name}")
|
||||
}
|
||||
emit(WcPairState.Approving.Result(sessionForApprove, either))
|
||||
}.onCompletion {
|
||||
if (it != null) {
|
||||
Timber.tag(WC_TAG).e(it, "Completed with error $pairRequest")
|
||||
} else {
|
||||
Timber.tag(WC_TAG).i("Completed successfully $pairRequest")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun approve(sessionForApprove: WcSessionApprove) {
|
||||
analytics.send(WcAnalyticEvents.PairButtonConnect)
|
||||
onCallTerminalAction.trySend(TerminalAction.Approve(sessionForApprove))
|
||||
}
|
||||
|
||||
override fun reject() {
|
||||
analytics.send(WcAnalyticEvents.ButtonCancel(WcAnalyticEvents.ButtonCancel.Type.Connection))
|
||||
onCallTerminalAction.trySend(TerminalAction.Reject)
|
||||
}
|
||||
|
||||
|
|
@ -119,9 +148,17 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
): Either<WcPairError, WcPairState.Proposal> = runCatching {
|
||||
val proposalNetwork = associateNetworksDelegate.associate(sessionProposal)
|
||||
val verificationInfo = blockAidVerifier.verifyDApp(DAppData(sessionProposal.url)).getOrElse {
|
||||
Timber.e("Failed to verify DApp: ${it.localizedMessage}")
|
||||
Timber.tag(WC_TAG).e(it, "Failed to verify DApp ${sessionProposal.name}")
|
||||
CheckDAppResult.FAILED_TO_VERIFY
|
||||
}
|
||||
val requestedNetworks = proposalNetwork
|
||||
.values.map { it.available.plus(it.required) }.flatten().toSet()
|
||||
analytics.send(
|
||||
WcAnalyticEvents.PairRequested(
|
||||
network = requestedNetworks,
|
||||
verificationInfo.name,
|
||||
),
|
||||
)
|
||||
val appMetaData = WcAppMetaData(
|
||||
name = sessionProposal.name,
|
||||
description = sessionProposal.description,
|
||||
|
|
|
|||
|
|
@ -3,12 +3,14 @@ package com.tangem.data.walletconnect.request
|
|||
import com.reown.walletkit.client.Wallet
|
||||
import com.tangem.data.walletconnect.utils.WcSdkObserver
|
||||
import com.tangem.data.walletconnect.utils.WcSdkSessionRequestConverter
|
||||
import com.tangem.data.walletconnect.utils.WC_TAG
|
||||
import com.tangem.domain.walletconnect.WcRequestService
|
||||
import com.tangem.domain.walletconnect.model.WcMethodName
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import timber.log.Timber
|
||||
|
||||
internal class DefaultWcRequestService(
|
||||
private val requestConverters: Set<WcRequestToUseCaseConverter>,
|
||||
|
|
@ -23,8 +25,10 @@ internal class DefaultWcRequestService(
|
|||
) {
|
||||
// Triggered when a Dapp sends SessionRequest to sign a transaction or a message
|
||||
val sr = WcSdkSessionRequestConverter.convert(sessionRequest)
|
||||
Timber.tag(WC_TAG).i("handle request $sr")
|
||||
val name = requestConverters.firstNotNullOfOrNull { it.toWcMethodName(sr) }
|
||||
?: WcMethodName.Unsupported(sr.request.method)
|
||||
Timber.tag(WC_TAG).i("handle request name $name")
|
||||
_wcRequest.trySend(name to sr)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,8 +5,10 @@ import arrow.core.left
|
|||
import arrow.core.right
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.reown.walletkit.client.WalletKit
|
||||
import com.tangem.data.walletconnect.utils.WC_TAG
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import timber.log.Timber
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
internal class DefaultWcRespondService : WcRespondService {
|
||||
|
|
@ -22,35 +24,18 @@ internal class DefaultWcRespondService : WcRespondService {
|
|||
),
|
||||
),
|
||||
onSuccess = {
|
||||
Timber.tag(WC_TAG).i("Successful respond for request $request")
|
||||
continuation.resume(Unit.right())
|
||||
},
|
||||
onError = {
|
||||
continuation.resume(it.throwable.left())
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun rejectRequest(request: WcSdkSessionRequest, message: String) =
|
||||
suspendCancellableCoroutine { continuation ->
|
||||
WalletKit.respondSessionRequest(
|
||||
params = Wallet.Params.SessionRequestResponse(
|
||||
sessionTopic = request.topic,
|
||||
jsonRpcResponse = Wallet.Model.JsonRpcResponse.JsonRpcError(
|
||||
id = request.request.id,
|
||||
code = 0,
|
||||
message = message,
|
||||
),
|
||||
),
|
||||
onSuccess = {
|
||||
continuation.resume(Unit.right())
|
||||
},
|
||||
onError = {
|
||||
Timber.tag(WC_TAG).e(it.throwable, "Failed respond for request $request")
|
||||
continuation.resume(it.throwable.left())
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun rejectRequestNonBlock(request: WcSdkSessionRequest, message: String) {
|
||||
Timber.tag(WC_TAG).i("reject request $request")
|
||||
WalletKit.respondSessionRequest(
|
||||
params = Wallet.Params.SessionRequestResponse(
|
||||
sessionTopic = request.topic,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,5 @@ import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
|||
|
||||
interface WcRespondService {
|
||||
suspend fun respond(request: WcSdkSessionRequest, response: String): Either<Throwable, Unit>
|
||||
suspend fun rejectRequest(request: WcSdkSessionRequest, message: String = ""): Either<Throwable, Unit>
|
||||
fun rejectRequestNonBlock(request: WcSdkSessionRequest, message: String = "")
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import com.reown.walletkit.client.WalletKit
|
|||
import com.tangem.data.walletconnect.pair.AssociateNetworksDelegate
|
||||
import com.tangem.data.walletconnect.utils.WcSdkObserver
|
||||
import com.tangem.data.walletconnect.utils.WcSdkSessionConverter
|
||||
import com.tangem.data.walletconnect.utils.WC_TAG
|
||||
import com.tangem.datasource.local.walletconnect.WalletConnectStore
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.model.WcSessionDTO
|
||||
|
|
@ -143,6 +144,7 @@ internal class DefaultWcSessionsManager(
|
|||
val haveSomeUnknown = unknownStoredSessions.isNotEmpty()
|
||||
|
||||
if (haveSomeUnknown) {
|
||||
Timber.tag(WC_TAG).i("removeUnknownSessions $unknownStoredSessions")
|
||||
store.removeSessions(unknownStoredSessions.toSet())
|
||||
}
|
||||
return haveSomeUnknown
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.data.walletconnect.sign
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.walletconnect.WcAnalyticEvents
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
|
||||
|
|
@ -16,6 +18,7 @@ internal abstract class BaseWcSignUseCase<MiddleAction, SignModel> :
|
|||
MiddleActionCollector<MiddleAction, SignModel> {
|
||||
|
||||
abstract val respondService: WcRespondService
|
||||
abstract val analytics: AnalyticsEventHandler
|
||||
|
||||
abstract val context: WcMethodUseCaseContext
|
||||
override val network: Network get() = context.network
|
||||
|
|
@ -25,17 +28,36 @@ internal abstract class BaseWcSignUseCase<MiddleAction, SignModel> :
|
|||
|
||||
protected val delegate by lazy {
|
||||
WcSignUseCaseDelegate(
|
||||
analytics = analytics,
|
||||
context = context,
|
||||
finalActionCollector = this,
|
||||
middleActionCollector = this,
|
||||
)
|
||||
}
|
||||
|
||||
init {
|
||||
analytics.send(
|
||||
WcAnalyticEvents.SignatureRequestReceived(
|
||||
session = context.session,
|
||||
rawRequest = context.rawSdkRequest,
|
||||
network = context.network,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun onCancel(currentState: WcSignState<SignModel>) {
|
||||
defaultReject()
|
||||
}
|
||||
|
||||
override fun sign() = delegate.sign()
|
||||
override fun cancel() = delegate.cancel()
|
||||
override fun sign() {
|
||||
analytics.send(WcAnalyticEvents.ButtonSign(context.rawSdkRequest))
|
||||
delegate.sign()
|
||||
}
|
||||
|
||||
override fun cancel() {
|
||||
analytics.send(WcAnalyticEvents.ButtonCancel(WcAnalyticEvents.ButtonCancel.Type.Sign))
|
||||
delegate.cancel()
|
||||
}
|
||||
protected fun middleAction(action: MiddleAction) = delegate.middleAction(action)
|
||||
|
||||
protected fun defaultReject() {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package com.tangem.data.walletconnect.sign
|
||||
|
||||
import arrow.core.left
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
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.WcAnalyticEvents
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
|
||||
import kotlinx.coroutines.Job
|
||||
|
|
@ -13,6 +15,8 @@ import kotlinx.coroutines.flow.*
|
|||
import kotlinx.coroutines.launch
|
||||
|
||||
internal class WcSignUseCaseDelegate<MiddleAction, SignModel>(
|
||||
private val analytics: AnalyticsEventHandler,
|
||||
private val context: WcMethodUseCaseContext,
|
||||
private val finalActionCollector: FinalActionCollector<SignModel>,
|
||||
private val middleActionCollector: MiddleActionCollector<MiddleAction, SignModel>,
|
||||
) : FinalActionCollector<SignModel> by finalActionCollector,
|
||||
|
|
@ -54,6 +58,27 @@ internal class WcSignUseCaseDelegate<MiddleAction, SignModel>(
|
|||
val errorResult = state.value.toResult(exception.left())
|
||||
state.update { errorResult }
|
||||
}
|
||||
.onEach { state ->
|
||||
val step = state.domainStep as? WcSignStep.Result ?: return@onEach
|
||||
val event = step.result.fold(
|
||||
ifLeft = {
|
||||
WcAnalyticEvents.SignatureRequestFailed(
|
||||
session = context.session,
|
||||
rawRequest = context.rawSdkRequest,
|
||||
network = context.network,
|
||||
it.message.orEmpty(),
|
||||
)
|
||||
},
|
||||
ifRight = {
|
||||
WcAnalyticEvents.SignatureRequestHandled(
|
||||
session = context.session,
|
||||
rawRequest = context.rawSdkRequest,
|
||||
network = context.network,
|
||||
)
|
||||
},
|
||||
)
|
||||
analytics.send(event)
|
||||
}
|
||||
|
||||
var signJob: Job? = null
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package com.tangem.data.walletconnect.utils
|
|||
import com.reown.walletkit.client.Wallet
|
||||
import com.reown.walletkit.client.WalletKit
|
||||
|
||||
const val WC_TAG = "Wallet Connect"
|
||||
|
||||
internal interface WcSdkObserver : WalletKit.WalletDelegate {
|
||||
|
||||
override val onSessionAuthenticate: ((Wallet.Model.SessionAuthenticate, Wallet.Model.VerifyContext) -> Unit)?
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.domain.blockaid.models.dapp.CheckDAppResult
|
|||
import com.domain.blockaid.models.dapp.DAppData
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.tangem.common.test.domain.wallet.MockUserWalletFactory
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.pair.AssociateNetworksDelegate
|
||||
import com.tangem.data.walletconnect.pair.CaipNamespaceDelegate
|
||||
import com.tangem.data.walletconnect.pair.DefaultWcPairUseCase
|
||||
|
|
@ -34,6 +35,7 @@ internal class DefaultWcPairUseCaseTest {
|
|||
private val sessionsManager: WcSessionsManager = mockk<WcSessionsManager>()
|
||||
private val associateNetworksDelegate: AssociateNetworksDelegate = mockk<AssociateNetworksDelegate>()
|
||||
private val caipNamespaceDelegate: CaipNamespaceDelegate = mockk<CaipNamespaceDelegate>()
|
||||
private val analytics: AnalyticsEventHandler = mockk<AnalyticsEventHandler>(relaxed = true)
|
||||
private val sdkDelegate: WcPairSdkDelegate = mockk<WcPairSdkDelegate>()
|
||||
private val blockAidVerifier: BlockAidVerifier = mockk<BlockAidVerifier>()
|
||||
|
||||
|
|
@ -101,6 +103,7 @@ internal class DefaultWcPairUseCaseTest {
|
|||
caipNamespaceDelegate = caipNamespaceDelegate,
|
||||
sdkDelegate = sdkDelegate,
|
||||
blockAidVerifier = blockAidVerifier,
|
||||
analytics = analytics,
|
||||
pairRequest = WcPairRequest(userWalletId = UserWalletId(""), uri = url, source = source),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,20 @@ package com.tangem.domain.walletconnect
|
|||
import app.cash.turbine.test
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.data.walletconnect.sign.FinalActionCollector
|
||||
import com.tangem.data.walletconnect.sign.MiddleActionCollector
|
||||
import com.tangem.data.walletconnect.sign.SignCollector
|
||||
import com.domain.blockaid.models.dapp.CheckDAppResult
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.common.test.domain.wallet.MockUserWalletFactory
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.sign.*
|
||||
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.model.WcSession
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcAppMetaData
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSession
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
|
||||
import io.mockk.mockk
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.FlowCollector
|
||||
|
|
@ -25,6 +31,36 @@ internal class WcSignUseCaseDelegateTest {
|
|||
private var finalActionCollector: FinalActionCollector<TestSignModel> =
|
||||
object : FinalActionCollector<TestSignModel> {}
|
||||
private val initSignModel = TestSignModel()
|
||||
private val analytics: AnalyticsEventHandler = mockk<AnalyticsEventHandler>(relaxed = true)
|
||||
private val rawRequestMock = WcSdkSessionRequest(
|
||||
topic = "",
|
||||
chainId = "",
|
||||
request = WcSdkSessionRequest.JSONRPCRequest(
|
||||
id = 0L,
|
||||
method = "",
|
||||
params = "",
|
||||
),
|
||||
)
|
||||
private val context: WcMethodUseCaseContext = WcMethodUseCaseContext(
|
||||
network = MockCryptoCurrencyFactory().ethereum.network,
|
||||
accountAddress = "",
|
||||
rawSdkRequest = rawRequestMock,
|
||||
session = WcSession(
|
||||
wallet = MockUserWalletFactory.create(),
|
||||
networks = setOf(),
|
||||
securityStatus = CheckDAppResult.FAILED_TO_VERIFY,
|
||||
sdkModel = WcSdkSession(
|
||||
topic = "",
|
||||
appMetaData = WcAppMetaData(
|
||||
name = "",
|
||||
description = "",
|
||||
url = "",
|
||||
icons = listOf(),
|
||||
redirect = "",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
private val initState = WcSignState(initSignModel, WcSignStep.PreSign)
|
||||
private val signing = initState.toSigning()
|
||||
|
|
@ -46,6 +82,16 @@ internal class WcSignUseCaseDelegateTest {
|
|||
emit(state.toResult(testException.left()))
|
||||
}
|
||||
|
||||
private fun createUseCaseDelegate(
|
||||
middleActionCollector: MiddleActionCollector<TestMiddleAction, TestSignModel>,
|
||||
finalActionCollector: FinalActionCollector<TestSignModel>,
|
||||
) = WcSignUseCaseDelegate(
|
||||
analytics = analytics,
|
||||
context = context,
|
||||
finalActionCollector = finalActionCollector,
|
||||
middleActionCollector = middleActionCollector,
|
||||
)
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
middleActionCollector = object : MiddleActionCollector<TestMiddleAction, TestSignModel> {}
|
||||
|
|
@ -59,7 +105,7 @@ internal class WcSignUseCaseDelegateTest {
|
|||
successSign(state)
|
||||
}
|
||||
}
|
||||
val useCase = WcSignUseCaseDelegate(
|
||||
val useCase = createUseCaseDelegate(
|
||||
finalActionCollector = finalActionCollector,
|
||||
middleActionCollector = middleActionCollector,
|
||||
)
|
||||
|
|
@ -77,7 +123,7 @@ internal class WcSignUseCaseDelegateTest {
|
|||
successSign(state)
|
||||
}
|
||||
}
|
||||
val useCase = WcSignUseCaseDelegate(
|
||||
val useCase = createUseCaseDelegate(
|
||||
finalActionCollector = finalActionCollector,
|
||||
middleActionCollector = middleActionCollector,
|
||||
)
|
||||
|
|
@ -99,7 +145,7 @@ internal class WcSignUseCaseDelegateTest {
|
|||
failedSign(state)
|
||||
}
|
||||
}
|
||||
val useCase = WcSignUseCaseDelegate(
|
||||
val useCase = createUseCaseDelegate(
|
||||
finalActionCollector = finalActionCollector,
|
||||
middleActionCollector = middleActionCollector,
|
||||
)
|
||||
|
|
@ -123,7 +169,7 @@ internal class WcSignUseCaseDelegateTest {
|
|||
throw exception
|
||||
}
|
||||
}
|
||||
val useCase = WcSignUseCaseDelegate(
|
||||
val useCase = createUseCaseDelegate(
|
||||
finalActionCollector = finalActionCollector,
|
||||
middleActionCollector = middleActionCollector,
|
||||
)
|
||||
|
|
@ -145,7 +191,7 @@ internal class WcSignUseCaseDelegateTest {
|
|||
emit(result)
|
||||
}
|
||||
}
|
||||
val useCase = WcSignUseCaseDelegate(
|
||||
val useCase = createUseCaseDelegate(
|
||||
finalActionCollector = finalActionCollector,
|
||||
middleActionCollector = middleActionCollector,
|
||||
)
|
||||
|
|
@ -176,7 +222,7 @@ internal class WcSignUseCaseDelegateTest {
|
|||
emit(expectedSignResult)
|
||||
}
|
||||
}
|
||||
val useCase = WcSignUseCaseDelegate(
|
||||
val useCase = createUseCaseDelegate(
|
||||
finalActionCollector = finalActionCollector,
|
||||
middleActionCollector = middleActionCollector,
|
||||
)
|
||||
|
|
@ -229,7 +275,7 @@ internal class WcSignUseCaseDelegateTest {
|
|||
emit(signModel.copy(testStr = middleAction.newTestStr))
|
||||
}
|
||||
}
|
||||
val useCase = WcSignUseCaseDelegate(
|
||||
val useCase = createUseCaseDelegate(
|
||||
finalActionCollector = finalActionCollector,
|
||||
middleActionCollector = middleActionCollector,
|
||||
)
|
||||
|
|
@ -276,7 +322,7 @@ internal class WcSignUseCaseDelegateTest {
|
|||
delay(4)
|
||||
}
|
||||
}
|
||||
val useCase = WcSignUseCaseDelegate(
|
||||
val useCase = createUseCaseDelegate(
|
||||
finalActionCollector = finalActionCollector,
|
||||
middleActionCollector = middleActionCollector,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ dependencies {
|
|||
implementation(projects.domain.walletConnect.models)
|
||||
implementation(projects.domain.blockaid.models)
|
||||
|
||||
/* Project - Core */
|
||||
implementation(projects.core.analytics)
|
||||
|
||||
/* Other */
|
||||
implementation(deps.moshi.adapters)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,162 @@
|
|||
package com.tangem.domain.walletconnect
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.model.WcSessionApprove
|
||||
import com.tangem.domain.walletconnect.model.WcSessionProposal
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
|
||||
sealed class WcAnalyticEvents(
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent(category = "Wallet Connect", event = event, params = params) {
|
||||
|
||||
class NewPairInitiated(source: WcPairRequest.Source) : WcAnalyticEvents(
|
||||
event = "Session Initiated",
|
||||
params = mapOf(
|
||||
AnalyticsParam.Key.SOURCE to when (source) {
|
||||
WcPairRequest.Source.QR -> "QR"
|
||||
WcPairRequest.Source.DEEPLINK -> "DeepLink"
|
||||
WcPairRequest.Source.CLIPBOARD -> "Clipboard"
|
||||
WcPairRequest.Source.ETC -> "etc"
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
data object PairButtonConnect : WcAnalyticEvents(
|
||||
event = "Button - Connect",
|
||||
)
|
||||
|
||||
class PairRequested(
|
||||
network: Set<Network>,
|
||||
domainVerification: String,
|
||||
) : WcAnalyticEvents(
|
||||
event = "dApp Connection Requested",
|
||||
params = mapOf(
|
||||
NETWORKS to network.joinToString(",") { it.name },
|
||||
DOMAIN_VERIFICATION to domainVerification,
|
||||
),
|
||||
)
|
||||
|
||||
data object PairFailed : WcAnalyticEvents(
|
||||
event = "Session Failed",
|
||||
)
|
||||
|
||||
class DAppConnected(
|
||||
sessionProposal: WcSessionProposal,
|
||||
sessionForApprove: WcSessionApprove,
|
||||
) : WcAnalyticEvents(
|
||||
event = "dApp Connected",
|
||||
params = mapOf(
|
||||
AnalyticsParam.Key.DAPP_NAME to sessionProposal.dAppMetaData.name,
|
||||
AnalyticsParam.Key.DAPP_URL to sessionProposal.dAppMetaData.url,
|
||||
AnalyticsParam.Key.BLOCKCHAIN to sessionForApprove.network.joinToString(",") { it.name },
|
||||
),
|
||||
)
|
||||
|
||||
class DAppConnectionFailed(
|
||||
errorCode: String,
|
||||
) : WcAnalyticEvents(
|
||||
event = "dApp Connection Failed",
|
||||
params = mapOf(
|
||||
AnalyticsParam.Key.ERROR_CODE to errorCode,
|
||||
),
|
||||
)
|
||||
|
||||
class SessionDisconnected(sessionProposal: WcSessionProposal) : WcAnalyticEvents(
|
||||
event = "dApp Disconnected",
|
||||
params = mapOf(
|
||||
AnalyticsParam.Key.DAPP_NAME to sessionProposal.dAppMetaData.name,
|
||||
AnalyticsParam.Key.DAPP_URL to sessionProposal.dAppMetaData.url,
|
||||
),
|
||||
)
|
||||
|
||||
class SignatureRequestReceived(
|
||||
session: WcSession,
|
||||
rawRequest: WcSdkSessionRequest,
|
||||
network: Network,
|
||||
) : WcAnalyticEvents(
|
||||
event = "Signature Request Received",
|
||||
params = mapOf(
|
||||
AnalyticsParam.Key.DAPP_NAME to session.sdkModel.appMetaData.name,
|
||||
AnalyticsParam.Key.DAPP_URL to session.sdkModel.appMetaData.url,
|
||||
AnalyticsParam.Key.METHOD_NAME to rawRequest.request.method,
|
||||
AnalyticsParam.Key.BLOCKCHAIN to network.name,
|
||||
),
|
||||
)
|
||||
|
||||
class SignatureRequestHandled(
|
||||
session: WcSession,
|
||||
rawRequest: WcSdkSessionRequest,
|
||||
network: Network,
|
||||
) : WcAnalyticEvents(
|
||||
event = "Signature Request Handled",
|
||||
params = mapOf(
|
||||
AnalyticsParam.Key.DAPP_NAME to session.sdkModel.appMetaData.name,
|
||||
AnalyticsParam.Key.DAPP_URL to session.sdkModel.appMetaData.url,
|
||||
AnalyticsParam.Key.METHOD_NAME to rawRequest.request.method,
|
||||
AnalyticsParam.Key.BLOCKCHAIN to network.name,
|
||||
),
|
||||
)
|
||||
|
||||
class SignatureRequestFailed(
|
||||
session: WcSession,
|
||||
rawRequest: WcSdkSessionRequest,
|
||||
network: Network,
|
||||
errorCode: String,
|
||||
) : WcAnalyticEvents(
|
||||
event = "Signature Request Failed",
|
||||
params = mapOf(
|
||||
AnalyticsParam.Key.DAPP_NAME to session.sdkModel.appMetaData.name,
|
||||
AnalyticsParam.Key.DAPP_URL to session.sdkModel.appMetaData.url,
|
||||
AnalyticsParam.Key.METHOD_NAME to rawRequest.request.method,
|
||||
AnalyticsParam.Key.BLOCKCHAIN to network.name,
|
||||
AnalyticsParam.Key.ERROR_CODE to errorCode,
|
||||
),
|
||||
)
|
||||
|
||||
class ButtonSign(
|
||||
rawRequest: WcSdkSessionRequest,
|
||||
) : WcAnalyticEvents(
|
||||
event = "Button - Sign",
|
||||
params = mapOf(
|
||||
AnalyticsParam.Key.METHOD_NAME to rawRequest.request.method,
|
||||
),
|
||||
)
|
||||
|
||||
class ButtonCancel(
|
||||
type: Type,
|
||||
) : WcAnalyticEvents(
|
||||
event = "Button - Sign",
|
||||
params = mapOf(
|
||||
AnalyticsParam.Key.TYPE to type.type,
|
||||
),
|
||||
) {
|
||||
enum class Type(val type: String) {
|
||||
Connection("Connection"),
|
||||
Sign("Sign"),
|
||||
}
|
||||
}
|
||||
|
||||
data object ButtonDisconnectAll : WcAnalyticEvents(
|
||||
event = "Button - Disconnect All",
|
||||
)
|
||||
|
||||
class ButtonDisconnect(
|
||||
session: WcSession,
|
||||
) : WcAnalyticEvents(
|
||||
event = "Button - Disconnect",
|
||||
params = mapOf(
|
||||
AnalyticsParam.Key.DAPP_NAME to session.sdkModel.appMetaData.name,
|
||||
AnalyticsParam.Key.DAPP_URL to session.sdkModel.appMetaData.url,
|
||||
),
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val NETWORKS = "Networks"
|
||||
const val DOMAIN_VERIFICATION = "Domain Verification"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.domain.walletconnect.usecase.disconnect
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.walletconnect.WcAnalyticEvents
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.repository.WcSessionsManager
|
||||
import kotlinx.coroutines.flow.first
|
||||
|
|
@ -9,22 +11,30 @@ import kotlinx.coroutines.flow.toList
|
|||
|
||||
class WcDisconnectUseCase(
|
||||
private val sessionsManager: WcSessionsManager,
|
||||
private val analytics: AnalyticsEventHandler,
|
||||
) {
|
||||
|
||||
suspend fun disconnectAll() {
|
||||
analytics.send(WcAnalyticEvents.ButtonDisconnectAll)
|
||||
sessionsManager.sessions.first()
|
||||
.flatMap { it.value }
|
||||
.map { session -> flow { emit(disconnect(session)) } }
|
||||
.map { session -> flow { emit(internalDisconnect(session)) } }
|
||||
.merge()
|
||||
.toList()
|
||||
}
|
||||
|
||||
suspend fun disconnect(topic: String) {
|
||||
val session = sessionsManager.findSessionByTopic(topic) ?: return
|
||||
disconnect(session)
|
||||
analytics.send(WcAnalyticEvents.ButtonDisconnect(session))
|
||||
internalDisconnect(session)
|
||||
}
|
||||
|
||||
suspend fun disconnect(session: WcSession) {
|
||||
analytics.send(WcAnalyticEvents.ButtonDisconnect(session))
|
||||
internalDisconnect(session)
|
||||
}
|
||||
|
||||
private suspend fun internalDisconnect(session: WcSession) {
|
||||
sessionsManager.removeSession(session)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import com.tangem.domain.walletconnect.usecase.blockaid.WcBlockAidEligibleTransa
|
|||
* ## 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
|
||||
* 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue