diff --git a/data/wallet-connect/build.gradle.kts b/data/wallet-connect/build.gradle.kts index 2b9321f602..dfdfe71d2c 100644 --- a/data/wallet-connect/build.gradle.kts +++ b/data/wallet-connect/build.gradle.kts @@ -30,6 +30,7 @@ dependencies { /* Project - Core */ implementation(projects.core.utils) + implementation(projects.core.analytics) /* DI */ implementation(deps.hilt.core) diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt index 84a40f03e0..f1fe67b26a 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/di/WalletConnectDataModule.kt @@ -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( diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/initialize/DefaultWcInitializeUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/initialize/DefaultWcInitializeUseCase.kt index 91db31c6c8..1e6e533e5d 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/initialize/DefaultWcInitializeUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/initialize/DefaultWcInitializeUseCase.kt @@ -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) } } } diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthMessageSignUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthMessageSignUseCase.kt index 817e5a2ddc..b1ec5e840d 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthMessageSignUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthMessageSignUseCase.kt @@ -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, diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSendTransactionUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSendTransactionUseCase.kt index 214c12f74a..3a560bc130 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSendTransactionUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSendTransactionUseCase.kt @@ -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(), diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTransactionUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTransactionUseCase.kt index 5033ddac8d..36b54ba3e7 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTransactionUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTransactionUseCase.kt @@ -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, diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTypedDataUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTypedDataUseCase.kt index 61ad1718c5..8e961267e1 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTypedDataUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthSignTypedDataUseCase.kt @@ -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, diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/DefaultWcSolanaSignAllTransactionUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/DefaultWcSolanaSignAllTransactionUseCase.kt index 0db6558250..c2fb4099c9 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/DefaultWcSolanaSignAllTransactionUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/DefaultWcSolanaSignAllTransactionUseCase.kt @@ -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, diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/DefaultWcSolanaSignTransactionUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/DefaultWcSolanaSignTransactionUseCase.kt index 946dd9d620..ee268c3122 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/DefaultWcSolanaSignTransactionUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/DefaultWcSolanaSignTransactionUseCase.kt @@ -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, diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaMessageSignUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaMessageSignUseCase.kt index 20a23c46e0..e82c5601ea 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaMessageSignUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaMessageSignUseCase.kt @@ -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(), WcMessageSignUseCase { diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt index 5bcbce241a..fc52444c3b 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt @@ -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 { 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 = 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, 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 cb39b52a5e..ddfb53cc8e 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 @@ -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, @@ -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) } } \ No newline at end of file diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/respond/DefaultWcRespondService.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/respond/DefaultWcRespondService.kt index 025e9834b2..57961795e5 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/respond/DefaultWcRespondService.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/respond/DefaultWcRespondService.kt @@ -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, diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/respond/WcRespondService.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/respond/WcRespondService.kt index 0eb8948d59..be259755f2 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/respond/WcRespondService.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/respond/WcRespondService.kt @@ -5,6 +5,5 @@ import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest interface WcRespondService { suspend fun respond(request: WcSdkSessionRequest, response: String): Either - suspend fun rejectRequest(request: WcSdkSessionRequest, message: String = ""): Either fun rejectRequestNonBlock(request: WcSdkSessionRequest, message: String = "") } \ No newline at end of file diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt index 1c537ef70d..c6239ed16c 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sessions/DefaultWcSessionsManager.kt @@ -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 diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/BaseWcSignUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/BaseWcSignUseCase.kt index ded283fe3e..55ea7f8786 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/BaseWcSignUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/BaseWcSignUseCase.kt @@ -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 : MiddleActionCollector { 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 : 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) { 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() { diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt index 3428b16217..55c77f3de3 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt @@ -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( + private val analytics: AnalyticsEventHandler, + private val context: WcMethodUseCaseContext, private val finalActionCollector: FinalActionCollector, private val middleActionCollector: MiddleActionCollector, ) : FinalActionCollector by finalActionCollector, @@ -54,6 +58,27 @@ internal class WcSignUseCaseDelegate( 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 diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcSdkObserver.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcSdkObserver.kt index 4c70570c4d..06637ecefd 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcSdkObserver.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcSdkObserver.kt @@ -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)? diff --git a/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/DefaultWcPairUseCaseTest.kt b/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/DefaultWcPairUseCaseTest.kt index 6a86ee96f2..bd8e58f43b 100644 --- a/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/DefaultWcPairUseCaseTest.kt +++ b/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/DefaultWcPairUseCaseTest.kt @@ -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() private val associateNetworksDelegate: AssociateNetworksDelegate = mockk() private val caipNamespaceDelegate: CaipNamespaceDelegate = mockk() + private val analytics: AnalyticsEventHandler = mockk(relaxed = true) private val sdkDelegate: WcPairSdkDelegate = mockk() private val blockAidVerifier: BlockAidVerifier = mockk() @@ -101,6 +103,7 @@ internal class DefaultWcPairUseCaseTest { caipNamespaceDelegate = caipNamespaceDelegate, sdkDelegate = sdkDelegate, blockAidVerifier = blockAidVerifier, + analytics = analytics, pairRequest = WcPairRequest(userWalletId = UserWalletId(""), uri = url, source = source), ) diff --git a/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/WcSignUseCaseDelegateTest.kt b/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/WcSignUseCaseDelegateTest.kt index b993555c51..4251b79b72 100644 --- a/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/WcSignUseCaseDelegateTest.kt +++ b/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/WcSignUseCaseDelegateTest.kt @@ -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 = object : FinalActionCollector {} private val initSignModel = TestSignModel() + private val analytics: AnalyticsEventHandler = mockk(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, + finalActionCollector: FinalActionCollector, + ) = WcSignUseCaseDelegate( + analytics = analytics, + context = context, + finalActionCollector = finalActionCollector, + middleActionCollector = middleActionCollector, + ) + @Before fun setup() { middleActionCollector = object : MiddleActionCollector {} @@ -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, ) diff --git a/domain/wallet-connect/build.gradle.kts b/domain/wallet-connect/build.gradle.kts index a2178f32a7..a79409d531 100644 --- a/domain/wallet-connect/build.gradle.kts +++ b/domain/wallet-connect/build.gradle.kts @@ -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) diff --git a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcAnalyticEvents.kt b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcAnalyticEvents.kt new file mode 100644 index 0000000000..03f186a19c --- /dev/null +++ b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcAnalyticEvents.kt @@ -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 = 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, + 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" + } +} \ No newline at end of file diff --git a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/disconnect/WcDisconnectUseCase.kt b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/disconnect/WcDisconnectUseCase.kt index 707dc20180..cb6c3a2497 100644 --- a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/disconnect/WcDisconnectUseCase.kt +++ b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/disconnect/WcDisconnectUseCase.kt @@ -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) } } \ No newline at end of file diff --git a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcMessageSignUseCase.kt b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcMessageSignUseCase.kt index 594ffa0213..07b48dff2d 100644 --- a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcMessageSignUseCase.kt +++ b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/method/WcMessageSignUseCase.kt @@ -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