Updated on 2026-08-14
This commit is contained in:
parent
58d34d0fa7
commit
fc4c7ef9ab
10 changed files with 132 additions and 145 deletions
|
|
@ -5,7 +5,6 @@ import com.squareup.moshi.Moshi
|
|||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.data.walletconnect.DefaultWalletConnectRepository
|
||||
import com.tangem.data.walletconnect.initialize.DefaultWcInitializeUseCase
|
||||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
import com.tangem.data.walletconnect.network.ethereum.WcEthNetwork
|
||||
import com.tangem.data.walletconnect.network.solana.WcSolanaNetwork
|
||||
import com.tangem.data.walletconnect.pair.AssociateNetworksDelegate
|
||||
|
|
@ -13,7 +12,7 @@ import com.tangem.data.walletconnect.pair.CaipNamespaceDelegate
|
|||
import com.tangem.data.walletconnect.pair.DefaultWcPairUseCase
|
||||
import com.tangem.data.walletconnect.pair.WcPairSdkDelegate
|
||||
import com.tangem.data.walletconnect.request.DefaultWcRequestService
|
||||
import com.tangem.data.walletconnect.request.WcMethodHandler
|
||||
import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter
|
||||
import com.tangem.data.walletconnect.respond.DefaultWcRespondService
|
||||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.data.walletconnect.sessions.DefaultWcSessionsManager
|
||||
|
|
@ -22,11 +21,9 @@ import com.tangem.datasource.di.SdkMoshi
|
|||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.datasource.local.walletconnect.WalletConnectStore
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletconnect.model.WcMethod
|
||||
import com.tangem.domain.walletconnect.model.legacy.WalletConnectSessionsRepository
|
||||
import com.tangem.domain.walletconnect.repository.WalletConnectRepository
|
||||
import com.tangem.domain.walletconnect.repository.WcSessionsManager
|
||||
import com.tangem.domain.walletconnect.request.WcRequestService
|
||||
import com.tangem.domain.walletconnect.usecase.initialize.WcInitializeUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
|
|
@ -114,37 +111,37 @@ internal object WalletConnectDataModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun defaultWcRequestService(
|
||||
sessionsManager: WcSessionsManager,
|
||||
respondService: WcRespondService,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
diHelperBox: DiHelperBox,
|
||||
): DefaultWcRequestService {
|
||||
val scope = CoroutineScope(SupervisorJob() + dispatchers.io)
|
||||
return DefaultWcRequestService(
|
||||
sessionsManager = sessionsManager,
|
||||
respondService = respondService,
|
||||
requestAdapters = diHelperBox.handlers,
|
||||
requestConverters = diHelperBox.handlers,
|
||||
scope = scope,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun wcRequestService(default: DefaultWcRequestService): WcRequestService = default
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun wcRespondService(): WcRespondService = DefaultWcRespondService()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun wcEthNetwork(@SdkMoshi moshi: Moshi): WcEthNetwork = WcEthNetwork(
|
||||
fun wcEthNetwork(
|
||||
@SdkMoshi moshi: Moshi,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
sessionsManager: WcSessionsManager,
|
||||
): WcEthNetwork = WcEthNetwork(
|
||||
moshi = moshi,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
sessionsManager = sessionsManager,
|
||||
)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun wcSolanaNetwork(): WcSolanaNetwork = WcSolanaNetwork()
|
||||
fun wcSolanaNetwork(excludedBlockchains: ExcludedBlockchains): WcSolanaNetwork = WcSolanaNetwork(
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
|
|
@ -162,12 +159,10 @@ internal object WalletConnectDataModule {
|
|||
diHelperBox: DiHelperBox,
|
||||
getWallets: GetWalletsUseCase,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
): AssociateNetworksDelegate = AssociateNetworksDelegate(
|
||||
namespaceConverters = diHelperBox.converters,
|
||||
getWallets = getWallets,
|
||||
currenciesRepository = currenciesRepository,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
|
||||
@Provides
|
||||
|
|
@ -176,14 +171,14 @@ internal object WalletConnectDataModule {
|
|||
handlers = setOf(
|
||||
ethNetwork,
|
||||
),
|
||||
converters = buildMap {
|
||||
ethNetwork.namespaceKey to ethNetwork
|
||||
solanaNetwork.namespaceKey to solanaNetwork
|
||||
},
|
||||
converters = setOf(
|
||||
ethNetwork,
|
||||
solanaNetwork,
|
||||
),
|
||||
)
|
||||
|
||||
internal class DiHelperBox(
|
||||
val converters: Map<NamespaceKey, WcNamespaceConverter>,
|
||||
val handlers: Set<WcMethodHandler<WcMethod>>,
|
||||
val converters: Set<WcNamespaceConverter>,
|
||||
val handlers: Set<WcRequestToUseCaseConverter>,
|
||||
)
|
||||
}
|
||||
|
|
@ -2,36 +2,50 @@ package com.tangem.data.walletconnect.network.ethereum
|
|||
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.data.walletconnect.model.CAIP2
|
||||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
import com.tangem.data.walletconnect.request.WcMethodHandler
|
||||
import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter
|
||||
import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter.Companion.fromJson
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.domain.walletconnect.model.WcMethod
|
||||
import com.tangem.domain.walletconnect.model.WcRequest
|
||||
import com.tangem.domain.walletconnect.usecase.WcUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.WcUseCasesFlowProvider
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.walletconnect.model.WcEthMethod
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import com.tangem.domain.walletconnect.repository.WcSessionsManager
|
||||
import com.tangem.domain.walletconnect.usecase.WcMethodUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
internal class WcEthNetwork(
|
||||
internal class WcEthNetwork constructor(
|
||||
private val moshi: Moshi,
|
||||
) : WcMethodHandler<WcEthMethod>, WcUseCasesFlowProvider, WcNamespaceConverter {
|
||||
|
||||
private val _useCases: Channel<WcUseCase> = Channel(Channel.BUFFERED)
|
||||
override val useCases = _useCases.receiveAsFlow()
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
private val sessionsManager: WcSessionsManager,
|
||||
) : WcRequestToUseCaseConverter, WcNamespaceConverter {
|
||||
|
||||
override val namespaceKey: NamespaceKey = NamespaceKey("eip155")
|
||||
|
||||
override fun canHandle(methodName: String): Boolean {
|
||||
return Name.entries.find { it.raw == methodName } != null
|
||||
override suspend fun toUseCase(request: WcSdkSessionRequest): WcMethodUseCase? {
|
||||
val methodKey = request.request.method
|
||||
val name = Name.entries.find { it.raw == methodKey } ?: return null
|
||||
val method: WcEthMethod = name.toMethod(request) ?: return null
|
||||
val session = sessionsManager.findSessionByTopic(request.topic) ?: return null
|
||||
val network = toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null
|
||||
return when (method) {
|
||||
is WcEthMethod.PersonalEthSign -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserialize(methodName: String, params: String): WcEthMethod? {
|
||||
val name = Name.entries.find { it.raw == methodName } ?: return null
|
||||
return when (name) {
|
||||
Name.Sign -> TODO()
|
||||
Name.PersonalSign -> TODO()
|
||||
private fun Name.toMethod(request: WcSdkSessionRequest): WcEthMethod? {
|
||||
val rawParams = request.request.params
|
||||
return when (this) {
|
||||
Name.EthSign,
|
||||
Name.PersonalSign,
|
||||
-> moshi.fromJson<List<String>>(rawParams)?.let { list ->
|
||||
val accountIndex = if (this == Name.EthSign) 0 else 1
|
||||
val messageIndex = if (this == Name.EthSign) 1 else 0
|
||||
val account = list.getOrNull(accountIndex) ?: return@let null
|
||||
val message = list.getOrNull(messageIndex) ?: return@let null
|
||||
WcEthMethod.PersonalEthSign(account = account, message = message)
|
||||
}
|
||||
Name.SignTypeData -> TODO()
|
||||
Name.SignTypeDataV4 -> TODO()
|
||||
Name.SignTransaction -> TODO()
|
||||
|
|
@ -39,16 +53,8 @@ internal class WcEthNetwork(
|
|||
}
|
||||
}
|
||||
|
||||
override fun handle(wcRequest: WcRequest<WcMethod>) {
|
||||
wcRequest as WcRequest<WcEthMethod>
|
||||
val useCase = when (wcRequest.method) {
|
||||
is WcEthMethod.PersonalEthSign -> TODO()
|
||||
}
|
||||
_useCases.trySend(useCase)
|
||||
}
|
||||
|
||||
enum class Name(val raw: String) {
|
||||
Sign("eth_sign"),
|
||||
EthSign("eth_sign"),
|
||||
PersonalSign("personal_sign"),
|
||||
SignTypeData("eth_signTypedData"),
|
||||
SignTypeDataV4("eth_signTypedData_v4"),
|
||||
|
|
@ -56,13 +62,18 @@ internal class WcEthNetwork(
|
|||
SendTransaction("eth_sendTransaction"),
|
||||
}
|
||||
|
||||
override fun toNetwork(chainId: String, wallet: UserWallet): Network? {
|
||||
return toNetwork(chainId, wallet, excludedBlockchains)
|
||||
}
|
||||
|
||||
override fun toBlockchain(chainId: CAIP2): Blockchain? {
|
||||
if (chainId.namespace != namespaceKey.key) return null
|
||||
val ethChainId = chainId.reference.toIntOrNull() ?: return null
|
||||
return Blockchain.fromChainId(ethChainId)
|
||||
}
|
||||
|
||||
override fun toCAIP2(blockchain: Blockchain): CAIP2? {
|
||||
override fun toCAIP2(network: Network): CAIP2? {
|
||||
val blockchain = Blockchain.fromId(network.id.value)
|
||||
if (!blockchain.isEvm()) return null
|
||||
val chainId = blockchain.getChainId() ?: return null
|
||||
return CAIP2(
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
package com.tangem.data.walletconnect.network.solana
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.data.walletconnect.model.CAIP2
|
||||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
internal class WcSolanaNetwork constructor(
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
) : WcNamespaceConverter {
|
||||
|
||||
internal class WcSolanaNetwork : WcNamespaceConverter {
|
||||
override val namespaceKey: NamespaceKey = NamespaceKey("solana")
|
||||
|
||||
override fun toBlockchain(chainId: CAIP2): Blockchain? {
|
||||
|
|
@ -17,7 +23,12 @@ internal class WcSolanaNetwork : WcNamespaceConverter {
|
|||
}
|
||||
}
|
||||
|
||||
override fun toCAIP2(blockchain: Blockchain): CAIP2? {
|
||||
override fun toNetwork(chainId: String, wallet: UserWallet): Network? {
|
||||
return toNetwork(chainId, wallet, excludedBlockchains)
|
||||
}
|
||||
|
||||
override fun toCAIP2(network: Network): CAIP2? {
|
||||
val blockchain = Blockchain.fromId(network.id.value)
|
||||
val chainId = when (blockchain) {
|
||||
Blockchain.Solana -> MAINNET_CHAIN_ID
|
||||
Blockchain.SolanaTestnet -> TESTNET_CHAIN_ID
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
package com.tangem.data.walletconnect.pair
|
||||
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.data.common.currency.getNetwork
|
||||
import com.tangem.data.walletconnect.model.CAIP2
|
||||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
|
|
@ -16,17 +11,16 @@ import com.tangem.domain.wallets.models.UserWallet
|
|||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
|
||||
internal class AssociateNetworksDelegate constructor(
|
||||
private val namespaceConverters: Map<NamespaceKey, WcNamespaceConverter>,
|
||||
private val namespaceConverters: Set<WcNamespaceConverter>,
|
||||
private val getWallets: GetWalletsUseCase,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
) {
|
||||
|
||||
@Throws(WcPairError.UnsupportedNetworks::class)
|
||||
suspend fun associate(sessionProposal: Wallet.Model.SessionProposal): Map<UserWallet, ProposalNetwork> {
|
||||
val userWallets = getWallets.invokeSync().filter { it.isMultiCurrency }
|
||||
val requiredNamespaces: Set<CAIP2> = sessionProposal.requiredNamespaces.setOfChainId()
|
||||
val optionalNamespaces: Set<CAIP2> = sessionProposal.optionalNamespaces.setOfChainId()
|
||||
val requiredNamespaces: Set<String> = sessionProposal.requiredNamespaces.setOfChainId()
|
||||
val optionalNamespaces: Set<String> = sessionProposal.optionalNamespaces.setOfChainId()
|
||||
|
||||
return userWallets
|
||||
.associateWith { wallet -> mapNetworksForWallet(wallet, requiredNamespaces, optionalNamespaces) }
|
||||
|
|
@ -34,8 +28,8 @@ internal class AssociateNetworksDelegate constructor(
|
|||
|
||||
private suspend fun mapNetworksForWallet(
|
||||
wallet: UserWallet,
|
||||
requiredNamespaces: Set<CAIP2>,
|
||||
optionalNamespaces: Set<CAIP2>,
|
||||
requiredNamespaces: Set<String>,
|
||||
optionalNamespaces: Set<String>,
|
||||
): ProposalNetwork {
|
||||
val walletNetworks = currenciesRepository.getMultiCurrencyWalletCurrenciesSync(wallet.walletId)
|
||||
.filterIsInstance<CryptoCurrency.Coin>()
|
||||
|
|
@ -47,23 +41,10 @@ internal class AssociateNetworksDelegate constructor(
|
|||
val available = mutableSetOf<Network>()
|
||||
val notAdded = mutableSetOf<Network>()
|
||||
|
||||
fun CAIP2.toBlockchain() = namespaceConverters[NamespaceKey(this.namespace)]?.toBlockchain(this)
|
||||
fun Blockchain.toNetwork() = getNetwork(
|
||||
blockchain = this,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = wallet.scanResponse,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
|
||||
requiredNamespaces.forEach { chainId ->
|
||||
val blockchain = chainId.toBlockchain()
|
||||
if (blockchain == null) {
|
||||
unknownRequired.add(missingNetworkName(chainId))
|
||||
return@forEach
|
||||
}
|
||||
val wcNetwork = blockchain.toNetwork()
|
||||
val wcNetwork = namespaceConverters.firstNotNullOfOrNull { it.toNetwork(chainId, wallet) }
|
||||
if (wcNetwork == null) {
|
||||
unknownRequired.add(missingNetworkName(blockchain))
|
||||
unknownRequired.add(missingNetworkName(chainId))
|
||||
return@forEach
|
||||
}
|
||||
val walletNetwork = walletNetworks.find { network -> wcNetwork.id == network.id }
|
||||
|
|
@ -74,7 +55,8 @@ internal class AssociateNetworksDelegate constructor(
|
|||
}
|
||||
}
|
||||
optionalNamespaces.forEach { chainId ->
|
||||
val wcNetwork = chainId.toBlockchain()?.toNetwork() ?: return@forEach
|
||||
val wcNetwork = namespaceConverters.firstNotNullOfOrNull { it.toNetwork(chainId, wallet) }
|
||||
?: return@forEach
|
||||
val walletNetwork = walletNetworks.find { network -> wcNetwork.id == network.id }
|
||||
if (walletNetwork == null) {
|
||||
available.add(wcNetwork)
|
||||
|
|
@ -92,10 +74,8 @@ internal class AssociateNetworksDelegate constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun Map<String, Wallet.Model.Namespace.Proposal>.setOfChainId(): Set<CAIP2> =
|
||||
this.values.flatMap { proposal -> proposal.chains ?: listOf() }
|
||||
.mapNotNull { rawChainId -> CAIP2.fromRaw(rawChainId) }.toSet()
|
||||
private fun Map<String, Wallet.Model.Namespace.Proposal>.setOfChainId(): Set<String> =
|
||||
this.values.flatMap { proposal -> proposal.chains ?: listOf() }.toSet()
|
||||
|
||||
private fun missingNetworkName(chainId: CAIP2): String = chainId.namespace.replaceFirstChar(Char::titlecase)
|
||||
private fun missingNetworkName(blockchain: Blockchain): String = blockchain.getCoinName()
|
||||
private fun missingNetworkName(chainId: String): String = chainId.replaceFirstChar(Char::titlecase)
|
||||
}
|
||||
|
|
@ -1,16 +1,14 @@
|
|||
package com.tangem.data.walletconnect.pair
|
||||
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.data.walletconnect.model.CAIP10
|
||||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
internal class CaipNamespaceDelegate constructor(
|
||||
private val namespaceConverters: Map<NamespaceKey, WcNamespaceConverter>,
|
||||
private val namespaceConverters: Set<WcNamespaceConverter>,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
) {
|
||||
|
||||
|
|
@ -19,14 +17,11 @@ internal class CaipNamespaceDelegate constructor(
|
|||
userWallet: UserWallet,
|
||||
networks: List<Network>,
|
||||
): Map<String, Wallet.Model.Namespace.Session> {
|
||||
val converters = namespaceConverters.values
|
||||
|
||||
val result = mutableMapOf<String, Session>()
|
||||
|
||||
networks.map { network ->
|
||||
val blockchain = Blockchain.fromId(network.id.value)
|
||||
val address = walletManagersFacade.getDefaultAddress(userWallet.walletId, network)
|
||||
val chainId = converters.firstOrNull { it.toCAIP2(blockchain) != null }?.toCAIP2(blockchain)
|
||||
val chainId = namespaceConverters.firstNotNullOfOrNull { it.toCAIP2(network) }
|
||||
requireNotNull(chainId)
|
||||
requireNotNull(address)
|
||||
CAIP10(chainId = chainId, accountAddress = address)
|
||||
|
|
|
|||
|
|
@ -1,25 +1,22 @@
|
|||
package com.tangem.data.walletconnect.request
|
||||
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.data.walletconnect.utils.WcSdkObserver
|
||||
import com.tangem.data.walletconnect.utils.WcSdkSessionRequestConverter
|
||||
import com.tangem.domain.walletconnect.model.WcMethod
|
||||
import com.tangem.domain.walletconnect.model.WcRequest
|
||||
import com.tangem.domain.walletconnect.repository.WcSessionsManager
|
||||
import com.tangem.domain.walletconnect.request.WcRequestService
|
||||
import com.tangem.domain.walletconnect.usecase.WcMethodUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.WcUseCasesFlowProvider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal class DefaultWcRequestService(
|
||||
private val sessionsManager: WcSessionsManager,
|
||||
private val respondService: WcRespondService,
|
||||
private val requestAdapters: Set<WcMethodHandler<WcMethod>>,
|
||||
private val requestConverters: Set<WcRequestToUseCaseConverter>,
|
||||
private val scope: CoroutineScope,
|
||||
) : WcRequestService, WcSdkObserver {
|
||||
) : WcSdkObserver, WcUseCasesFlowProvider {
|
||||
|
||||
override val requests: MutableSharedFlow<WcRequest<*>> = MutableSharedFlow()
|
||||
private val _useCases: Channel<WcMethodUseCase> = Channel(Channel.BUFFERED)
|
||||
override val useCases = _useCases.receiveAsFlow()
|
||||
|
||||
override fun onSessionRequest(
|
||||
sessionRequest: Wallet.Model.SessionRequest,
|
||||
|
|
@ -27,21 +24,10 @@ internal class DefaultWcRequestService(
|
|||
) {
|
||||
// Triggered when a Dapp sends SessionRequest to sign a transaction or a message
|
||||
val sr = WcSdkSessionRequestConverter.convert(sessionRequest)
|
||||
val method = sr.request.method
|
||||
val params = sr.request.params
|
||||
scope.launch {
|
||||
val session = sessionsManager.findSessionByTopic(sr.topic)
|
||||
val handler: WcMethodHandler<WcMethod>? = requestAdapters.firstOrNull { it.canHandle(method) }
|
||||
|
||||
val deserialized: WcMethod? = handler?.deserialize(method, params)
|
||||
if (handler == null || deserialized == null || session == null) {
|
||||
respondService.rejectRequest(sr, "UnsupportedMethod") // todo(wc) use our domain error
|
||||
return@launch
|
||||
}
|
||||
|
||||
val wcRequest = WcRequest(sr, session, deserialized)
|
||||
handler.handle(wcRequest)
|
||||
requests.emit(wcRequest)
|
||||
val useCase = requestConverters.firstNotNullOfOrNull { it.toUseCase(sr) }
|
||||
?: return@launch // todo(wc) handle unsupported
|
||||
_useCases.trySend(useCase)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package com.tangem.data.walletconnect.request
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.adapter
|
||||
import com.tangem.domain.walletconnect.model.WcMethod
|
||||
import com.tangem.domain.walletconnect.model.WcRequest
|
||||
|
||||
interface WcMethodHandler<out M : WcMethod> {
|
||||
fun canHandle(methodName: String): Boolean
|
||||
fun deserialize(methodName: String, params: String): M?
|
||||
fun handle(wcRequest: WcRequest<WcMethod>)
|
||||
|
||||
companion object {
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
inline fun <reified T> fromJson(params: String, moshi: Moshi): T? =
|
||||
runCatching { moshi.adapter<T>().fromJsonValue(params) }.getOrNull()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.data.walletconnect.request
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.adapter
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import com.tangem.domain.walletconnect.usecase.WcMethodUseCase
|
||||
|
||||
interface WcRequestToUseCaseConverter {
|
||||
suspend fun toUseCase(request: WcSdkSessionRequest): WcMethodUseCase?
|
||||
|
||||
companion object {
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
inline fun <reified T> Moshi.fromJson(params: String): T? =
|
||||
runCatching { this.adapter<T>().fromJson(params) }.getOrNull()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,31 @@
|
|||
package com.tangem.data.walletconnect.utils
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.data.common.currency.getNetwork
|
||||
import com.tangem.data.walletconnect.model.CAIP2
|
||||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
internal interface WcNamespaceConverter {
|
||||
|
||||
val namespaceKey: NamespaceKey
|
||||
|
||||
fun toBlockchain(chainId: CAIP2): Blockchain?
|
||||
fun toCAIP2(blockchain: Blockchain): CAIP2?
|
||||
fun toBlockchain(chainId: String): Blockchain? = toCAIP2(chainId)?.let { caip2 -> toBlockchain(caip2) }
|
||||
|
||||
fun toCAIP2(network: Network): CAIP2?
|
||||
fun toCAIP2(chainId: String): CAIP2? = CAIP2.fromRaw(chainId)
|
||||
|
||||
fun toNetwork(chainId: String, wallet: UserWallet): Network?
|
||||
fun toNetwork(chainId: String, wallet: UserWallet, excludedBlockchains: ExcludedBlockchains): Network? {
|
||||
val blockchain = toBlockchain(chainId) ?: return null
|
||||
return getNetwork(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = wallet.scanResponse,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
package com.tangem.domain.walletconnect.request
|
||||
|
||||
import com.tangem.domain.walletconnect.model.WcRequest
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface WcRequestService {
|
||||
val requests: Flow<WcRequest<*>>
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue