From 0f9ba0ce7e6ec88a06548feede0b389f6c08a738 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 25 Apr 2025 15:44:00 +0700 Subject: [PATCH] Updated on 2026-08-14 --- .../di/WalletConnectDataModule.kt | 24 +++++++----------- .../initialize/DefaultWcInitializeUseCase.kt | 8 +++++- .../pair/DefaultWcPairService.kt | 17 +++++++++++++ .../pair/DefaultWcPairUseCase.kt | 19 +++++++++----- .../walletconnect/DefaultWcPairUseCaseTest.kt | 25 ++++++++++++------- domain/wallet-connect/models/build.gradle.kts | 4 +++ .../walletconnect/model/WcPairRequest.kt | 11 ++++++++ .../model/sdkcopy/WcSdkSessionRequest.kt | 4 +++ .../domain/walletconnect/WcPairService.kt | 10 ++++++++ .../usecase/initialize/WcInitializeUseCase.kt | 2 +- .../usecase/pair/WcPairUseCase.kt | 11 ++++---- .../components/ConnectionsComponent.kt | 4 +-- .../components/WcAppInfoContainerComponent.kt | 4 +-- 13 files changed, 101 insertions(+), 42 deletions(-) create mode 100644 data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairService.kt create mode 100644 domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcPairRequest.kt create mode 100644 domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcPairService.kt 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 3c2b20e4f5..5035e927cd 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 @@ -9,6 +9,7 @@ import com.tangem.data.walletconnect.network.ethereum.WcEthNetwork import com.tangem.data.walletconnect.network.solana.WcSolanaNetwork import com.tangem.data.walletconnect.pair.AssociateNetworksDelegate import com.tangem.data.walletconnect.pair.CaipNamespaceDelegate +import com.tangem.data.walletconnect.pair.DefaultWcPairService import com.tangem.data.walletconnect.pair.DefaultWcPairUseCase import com.tangem.data.walletconnect.pair.WcPairSdkDelegate import com.tangem.data.walletconnect.request.DefaultWcRequestService @@ -18,10 +19,11 @@ import com.tangem.data.walletconnect.respond.WcRespondService import com.tangem.data.walletconnect.sessions.DefaultWcSessionsManager import com.tangem.data.walletconnect.utils.WcNamespaceConverter import com.tangem.datasource.di.SdkMoshi +import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.datasource.local.walletconnect.WalletConnectStore -import com.tangem.domain.blockaid.BlockAidVerifier import com.tangem.domain.tokens.repository.CurrenciesRepository +import com.tangem.domain.walletconnect.WcPairService import com.tangem.domain.walletconnect.model.legacy.WalletConnectSessionsRepository import com.tangem.domain.walletconnect.repository.WalletConnectRepository import com.tangem.domain.walletconnect.repository.WcSessionsManager @@ -58,32 +60,24 @@ internal object WalletConnectDataModule { sessionsManager: DefaultWcSessionsManager, networkService: DefaultWcRequestService, pairSdkDelegate: WcPairSdkDelegate, + environmentConfigStorage: EnvironmentConfigStorage, + dispatchers: CoroutineDispatcherProvider, ): WcInitializeUseCase = DefaultWcInitializeUseCase( application = application, sessionsManager = sessionsManager, networkService = networkService, pairSdkDelegate = pairSdkDelegate, + environmentConfigStorage = environmentConfigStorage, + dispatchers = dispatchers, ) @Provides @Singleton - fun defaultWcPairUseCase( - sessionsManager: WcSessionsManager, - associateNetworksDelegate: AssociateNetworksDelegate, - caipNamespaceDelegate: CaipNamespaceDelegate, - sdkDelegate: WcPairSdkDelegate, - blockAidVerifier: BlockAidVerifier, - ): DefaultWcPairUseCase = DefaultWcPairUseCase( - sessionsManager = sessionsManager, - associateNetworksDelegate = associateNetworksDelegate, - caipNamespaceDelegate = caipNamespaceDelegate, - sdkDelegate = sdkDelegate, - blockAidVerifier = blockAidVerifier, - ) + fun defaultWcPairUseCase(): WcPairService = DefaultWcPairService() @Provides @Singleton - fun wcPairUseCase(default: DefaultWcPairUseCase): WcPairUseCase = default + fun wcPairUseCaseFactory(default: DefaultWcPairUseCase.Factory): WcPairUseCase.Factory = default @Provides @Singleton 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..64ea5578f6 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,7 +10,10 @@ 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.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.domain.walletconnect.usecase.initialize.WcInitializeUseCase +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.withContext import timber.log.Timber internal class DefaultWcInitializeUseCase( @@ -18,6 +21,8 @@ internal class DefaultWcInitializeUseCase( private val sessionsManager: DefaultWcSessionsManager, private val networkService: DefaultWcRequestService, private val pairSdkDelegate: WcPairSdkDelegate, + private val environmentConfigStorage: EnvironmentConfigStorage, + private val dispatchers: CoroutineDispatcherProvider, ) : WcInitializeUseCase { private val wcSdkObservers = mutableSetOf( @@ -26,7 +31,8 @@ internal class DefaultWcInitializeUseCase( pairSdkDelegate, ) - override fun init(projectId: String) { + override suspend fun init() = withContext(dispatchers.io) { + val projectId = environmentConfigStorage.getConfigSync().walletConnectProjectId val relayUrl = "relay.walletconnect.com" val serverUrl = "wss://$relayUrl?projectId=$projectId" val connectionType = ConnectionType.AUTOMATIC diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairService.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairService.kt new file mode 100644 index 0000000000..bb0c819b4b --- /dev/null +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairService.kt @@ -0,0 +1,17 @@ +package com.tangem.data.walletconnect.pair + +import com.tangem.domain.walletconnect.WcPairService +import com.tangem.domain.walletconnect.model.WcPairRequest +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.receiveAsFlow +import javax.inject.Inject + +class DefaultWcPairService @Inject constructor() : WcPairService { + private val _pairFlow: Channel = Channel(Channel.BUFFERED) + override val pairFlow: Flow = _pairFlow.receiveAsFlow() + + override fun pair(request: WcPairRequest) { + _pairFlow.trySend(request) + } +} \ No newline at end of file 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 107fb0289f..fc91e5eefe 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 @@ -9,15 +9,15 @@ import com.domain.blockaid.models.dapp.DAppData import com.reown.walletkit.client.Wallet import com.tangem.data.walletconnect.utils.WcSdkSessionConverter import com.tangem.domain.blockaid.BlockAidVerifier -import com.tangem.domain.walletconnect.model.WcPairError -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.* import com.tangem.domain.walletconnect.model.sdkcopy.WcAppMetaData import com.tangem.domain.walletconnect.repository.WcSessionsManager import com.tangem.domain.walletconnect.usecase.pair.WcPairState import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase import com.tangem.domain.wallets.models.UserWallet +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 @@ -27,17 +27,19 @@ import timber.log.Timber val unsupportedDApps = listOf("dYdX", "dYdX v4", "Apex Pro", "The Sandbox") -internal class DefaultWcPairUseCase( +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, + @Assisted private val pairRequest: WcPairRequest, ) : WcPairUseCase { private val onCallTerminalAction = Channel() - override fun pairFlow(uri: String, source: WcPairUseCase.Source): Flow { + override operator fun invoke(): Flow { + val (uri: String, source: WcPairRequest.Source) = pairRequest return flow { emit(WcPairState.Loading) @@ -151,4 +153,9 @@ internal class DefaultWcPairUseCase( data class Approve(val sessionForApprove: WcSessionApprove) : TerminalAction data object Reject : TerminalAction } + + @AssistedFactory + interface Factory : WcPairUseCase.Factory { + override fun create(pairRequest: WcPairRequest): DefaultWcPairUseCase + } } \ No newline at end of file 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 2a6827c8c9..1792340585 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 @@ -15,11 +15,11 @@ import com.tangem.data.walletconnect.pair.WcPairSdkDelegate import com.tangem.data.walletconnect.utils.WcSdkSessionConverter import com.tangem.domain.blockaid.BlockAidVerifier import com.tangem.domain.walletconnect.model.WcPairError +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.repository.WcSessionsManager import com.tangem.domain.walletconnect.usecase.pair.WcPairState -import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase import io.mockk.coEvery import io.mockk.coVerifyOrder import io.mockk.mockk @@ -37,7 +37,7 @@ internal class DefaultWcPairUseCaseTest { private val blockAidVerifier: BlockAidVerifier = mockk() private val url = "testUrl" - private val source = WcPairUseCase.Source.QR + private val source = WcPairRequest.Source.QR private val loading = WcPairState.Loading private val sdkProposal: Wallet.Model.SessionProposal get() = Wallet.Model.SessionProposal( @@ -93,12 +93,13 @@ internal class DefaultWcPairUseCaseTest { securityStatus = CheckDAppResult.SAFE, ) - private val useCase = DefaultWcPairUseCase( + private fun useCaseFactory() = DefaultWcPairUseCase( sessionsManager = sessionsManager, associateNetworksDelegate = associateNetworksDelegate, caipNamespaceDelegate = caipNamespaceDelegate, sdkDelegate = sdkDelegate, blockAidVerifier = blockAidVerifier, + pairRequest = WcPairRequest(url, source), ) @Before @@ -118,7 +119,8 @@ internal class DefaultWcPairUseCaseTest { coEvery { sdkDelegate.pair(url) } returns sdkProposal.right() coEvery { blockAidVerifier.verifyDApp(any()) } returns Either.catch { CheckDAppResult.SAFE } - useCase.pairFlow(url, source).test { + val useCase = useCaseFactory() + useCase.invoke().test { assertEquals(loading, awaitItem()) coVerifyOrder { sdkDelegate.pair(url) @@ -140,7 +142,8 @@ internal class DefaultWcPairUseCaseTest { coEvery { sessionsManager.saveSession(sessionForSave) } returns Unit coEvery { blockAidVerifier.verifyDApp(any()) } returns Either.catch { CheckDAppResult.SAFE } - useCase.pairFlow(url, source).test { + val useCase = useCaseFactory() + useCase.invoke().test { assertEquals(loading, awaitItem()) coVerifyOrder { sdkDelegate.pair(url) @@ -169,7 +172,8 @@ internal class DefaultWcPairUseCaseTest { coEvery { sdkDelegate.rejectSession(proposerPublicKey) } returns Unit coEvery { blockAidVerifier.verifyDApp(any()) } returns Either.catch { CheckDAppResult.SAFE } - useCase.pairFlow(url, source).test { + val useCase = useCaseFactory() + useCase.invoke().test { assertEquals(loading, awaitItem()) coVerifyOrder { sdkDelegate.pair(url) @@ -189,7 +193,8 @@ internal class DefaultWcPairUseCaseTest { coEvery { sdkDelegate.pair(url) } returns unsupportedSdkProposal.right() val unsupportedDAppError = WcPairState.Error(WcPairError.UnsupportedDApp) - useCase.pairFlow(url, source).test { + val useCase = useCaseFactory() + useCase.invoke().test { assertEquals(loading, awaitItem()) coVerifyOrder { sdkDelegate.pair(url) @@ -205,7 +210,8 @@ internal class DefaultWcPairUseCaseTest { coEvery { sdkDelegate.pair(url) } returns error.left() val errorState = WcPairState.Error(error) - useCase.pairFlow(url, source).test { + val useCase = useCaseFactory() + useCase.invoke().test { assertEquals(loading, awaitItem()) coVerifyOrder { sdkDelegate.pair(url) @@ -225,7 +231,8 @@ internal class DefaultWcPairUseCaseTest { val errorResult = WcPairState.Approving.Result(sessionForApprove, error) - useCase.pairFlow(url, source).test { + val useCase = useCaseFactory() + useCase.invoke().test { assertEquals(loading, awaitItem()) coVerifyOrder { sdkDelegate.pair(url) diff --git a/domain/wallet-connect/models/build.gradle.kts b/domain/wallet-connect/models/build.gradle.kts index 4fd593d3d4..f7455512a0 100644 --- a/domain/wallet-connect/models/build.gradle.kts +++ b/domain/wallet-connect/models/build.gradle.kts @@ -1,6 +1,7 @@ plugins { alias(deps.plugins.kotlin.jvm) alias(deps.plugins.ksp) + alias(deps.plugins.kotlin.serialization) id("configuration") } dependencies { @@ -13,4 +14,7 @@ dependencies { /* Other */ implementation(deps.moshi) ksp(deps.moshi.kotlin.codegen) + + /* Utils */ + implementation(deps.kotlin.serialization) } \ No newline at end of file diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcPairRequest.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcPairRequest.kt new file mode 100644 index 0000000000..1c1c3f3674 --- /dev/null +++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcPairRequest.kt @@ -0,0 +1,11 @@ +package com.tangem.domain.walletconnect.model + +import kotlinx.serialization.Serializable + +@Serializable +data class WcPairRequest( + val uri: String, + val source: Source, +) { + enum class Source { QR, DEEPLINK, CLIPBOARD, ETC } +} \ No newline at end of file diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcSdkSessionRequest.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcSdkSessionRequest.kt index 7b2ed2ff37..02240181d0 100644 --- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcSdkSessionRequest.kt +++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/sdkcopy/WcSdkSessionRequest.kt @@ -1,14 +1,18 @@ package com.tangem.domain.walletconnect.model.sdkcopy +import kotlinx.serialization.Serializable + /** * copy of [com.reown.walletkit.client.Wallet.Model.SessionRequest] */ +@Serializable data class WcSdkSessionRequest( val topic: String, val chainId: String?, val request: JSONRPCRequest, ) { + @Serializable data class JSONRPCRequest( val id: Long, val method: String, diff --git a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcPairService.kt b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcPairService.kt new file mode 100644 index 0000000000..e996aa25ac --- /dev/null +++ b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcPairService.kt @@ -0,0 +1,10 @@ +package com.tangem.domain.walletconnect + +import com.tangem.domain.walletconnect.model.WcPairRequest +import kotlinx.coroutines.flow.Flow + +interface WcPairService { + val pairFlow: Flow + + fun pair(request: WcPairRequest) +} \ No newline at end of file diff --git a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/initialize/WcInitializeUseCase.kt b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/initialize/WcInitializeUseCase.kt index 71f465a43f..0e00484903 100644 --- a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/initialize/WcInitializeUseCase.kt +++ b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/initialize/WcInitializeUseCase.kt @@ -1,5 +1,5 @@ package com.tangem.domain.walletconnect.usecase.initialize interface WcInitializeUseCase { - fun init(projectId: String) + suspend fun init() } \ No newline at end of file diff --git a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/pair/WcPairUseCase.kt b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/pair/WcPairUseCase.kt index b926213140..1097cfc7a5 100644 --- a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/pair/WcPairUseCase.kt +++ b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/usecase/pair/WcPairUseCase.kt @@ -1,20 +1,19 @@ package com.tangem.domain.walletconnect.usecase.pair import arrow.core.Either -import com.tangem.domain.walletconnect.model.WcPairError -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.* import kotlinx.coroutines.flow.Flow interface WcPairUseCase { - fun pairFlow(uri: String, source: Source): Flow + operator fun invoke(): Flow fun approve(sessionForApprove: WcSessionApprove) fun reject() - enum class Source { QR, DEEPLINK, CLIPBOARD, ETC } + interface Factory { + fun create(pairRequest: WcPairRequest): WcPairUseCase + } } sealed interface WcPairState { diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/ConnectionsComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/ConnectionsComponent.kt index 79b63e953b..0c311f6f4a 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/ConnectionsComponent.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/ConnectionsComponent.kt @@ -13,7 +13,7 @@ import com.tangem.core.decompose.context.childByContext import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.ui.decompose.ComposableBottomSheetComponent import com.tangem.core.ui.decompose.ComposableContentComponent -import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase +import com.tangem.domain.walletconnect.model.WcPairRequest import com.tangem.features.walletconnect.connections.model.WcConnectionsModel import com.tangem.features.walletconnect.connections.routes.WcConnectionsBottomSheetRoutes import com.tangem.features.walletconnect.connections.ui.WcConnectionsContent @@ -48,7 +48,7 @@ internal class ConnectionsComponent( appComponentContext = childByContext(componentContext), params = WcAppInfoContainerComponent.Params( wcUrl = config.wcUrl, - source = WcPairUseCase.Source.QR, + source = WcPairRequest.Source.QR, onDismiss = model.bottomSheetNavigation::dismiss, ), ) diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcAppInfoContainerComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcAppInfoContainerComponent.kt index 83f3853ca6..39c9b6740d 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcAppInfoContainerComponent.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcAppInfoContainerComponent.kt @@ -20,7 +20,7 @@ import com.tangem.core.ui.decompose.ComposableBottomSheetComponent import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.res.TangemTheme -import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase +import com.tangem.domain.walletconnect.model.WcPairRequest import com.tangem.features.walletconnect.connections.model.WcAppInfoModel import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes import com.tangem.features.walletconnect.impl.R @@ -103,5 +103,5 @@ internal class WcAppInfoContainerComponent( WcAppInfoRoutes.SelectWallet -> TODO() } - data class Params(val wcUrl: String, val source: WcPairUseCase.Source, val onDismiss: () -> Unit) + data class Params(val wcUrl: String, val source: WcPairRequest.Source, val onDismiss: () -> Unit) } \ No newline at end of file