Updated on 2026-08-14
This commit is contained in:
parent
d327640e9f
commit
bbd1fc9ace
13 changed files with 231 additions and 103 deletions
|
|
@ -16,6 +16,7 @@ import com.tangem.data.walletconnect.respond.DefaultWcRespondService
|
|||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.data.walletconnect.sessions.DefaultWcSessionsManager
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.data.walletconnect.utils.WcNetworksConverter
|
||||
import com.tangem.datasource.di.SdkMoshi
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.datasource.local.walletconnect.WalletConnectStore
|
||||
|
|
@ -91,7 +92,7 @@ internal object WalletConnectDataModule {
|
|||
dispatchers: CoroutineDispatcherProvider,
|
||||
legacyStore: WalletConnectSessionsRepository,
|
||||
getWallets: GetWalletsUseCase,
|
||||
associateNetworks: AssociateNetworksDelegate,
|
||||
wcNetworksConverter: WcNetworksConverter,
|
||||
analytics: AnalyticsEventHandler,
|
||||
): DefaultWcSessionsManager {
|
||||
val scope = CoroutineScope(SupervisorJob() + dispatchers.io)
|
||||
|
|
@ -100,7 +101,7 @@ internal object WalletConnectDataModule {
|
|||
dispatchers = dispatchers,
|
||||
legacyStore = legacyStore,
|
||||
getWallets = getWallets,
|
||||
associateNetworks = associateNetworks,
|
||||
wcNetworksConverter = wcNetworksConverter,
|
||||
analytics = analytics,
|
||||
scope = scope,
|
||||
)
|
||||
|
|
@ -133,11 +134,11 @@ internal object WalletConnectDataModule {
|
|||
@SdkMoshi moshi: Moshi,
|
||||
sessionsManager: WcSessionsManager,
|
||||
factories: WcEthNetwork.Factories,
|
||||
namespaceConverter: WcEthNetwork.NamespaceConverter,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
wcNetworksConverter: WcNetworksConverter,
|
||||
): WcEthNetwork = WcEthNetwork(
|
||||
moshi = moshi,
|
||||
namespaceConverter = namespaceConverter,
|
||||
networksConverter = wcNetworksConverter,
|
||||
sessionsManager = sessionsManager,
|
||||
factories = factories,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
|
|
@ -147,7 +148,7 @@ internal object WalletConnectDataModule {
|
|||
@Singleton
|
||||
fun wcSolanaNetwork(
|
||||
@SdkMoshi moshi: Moshi,
|
||||
namespaceConverter: WcSolanaNetwork.NamespaceConverter,
|
||||
wcNetworksConverter: WcNetworksConverter,
|
||||
sessionsManager: WcSessionsManager,
|
||||
factories: WcSolanaNetwork.Factories,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
|
|
@ -155,7 +156,7 @@ internal object WalletConnectDataModule {
|
|||
moshi = moshi,
|
||||
sessionsManager = sessionsManager,
|
||||
factories = factories,
|
||||
namespaceConverter = namespaceConverter,
|
||||
networksConverter = wcNetworksConverter,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
)
|
||||
|
||||
|
|
@ -164,9 +165,27 @@ internal object WalletConnectDataModule {
|
|||
fun caipNamespaceDelegate(
|
||||
namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
wcNetworksConverter: WcNetworksConverter,
|
||||
): CaipNamespaceDelegate = CaipNamespaceDelegate(
|
||||
namespaceConverters = namespaceConverters,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
wcNetworksConverter = wcNetworksConverter,
|
||||
)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun wcNetworksConverter(
|
||||
namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): WcNetworksConverter = WcNetworksConverter(
|
||||
namespaceConverters = namespaceConverters,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
currenciesRepository = currenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter
|
|||
import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter.Companion.fromJson
|
||||
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.data.walletconnect.utils.WcNetworksConverter
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.walletconnect.model.*
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
|
|
@ -23,7 +24,7 @@ internal class WcEthNetwork(
|
|||
private val moshi: Moshi,
|
||||
private val sessionsManager: WcSessionsManager,
|
||||
private val factories: Factories,
|
||||
private val namespaceConverter: NamespaceConverter,
|
||||
private val networksConverter: WcNetworksConverter,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
) : WcRequestToUseCaseConverter {
|
||||
|
||||
|
|
@ -37,20 +38,34 @@ internal class WcEthNetwork(
|
|||
override suspend fun toUseCase(request: WcSdkSessionRequest): WcMethodUseCase? {
|
||||
val name = toWcMethodName(request) ?: return null
|
||||
val session = sessionsManager.findSessionByTopic(request.topic) ?: return null
|
||||
val method: WcEthMethod = name.toMethod(request, session.wallet) ?: return null
|
||||
val network = namespaceConverter.toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null
|
||||
val walletManagerAddress = walletManagersFacade.getDefaultAddress(session.wallet.walletId, network).orEmpty()
|
||||
val wallet = session.wallet
|
||||
val chainId = request.chainId.orEmpty()
|
||||
val method: WcEthMethod = name.toMethod(request, wallet) ?: return null
|
||||
suspend fun anyExistNetwork() = networksConverter.mainOrAnyWalletNetworkForRequest(chainId, wallet)
|
||||
|
||||
val accountAddress = when (method) {
|
||||
is WcEthMethod.MessageSign -> method.account
|
||||
is WcEthMethod.SendTransaction -> method.transaction.from
|
||||
is WcEthMethod.SignTransaction -> method.transaction.from
|
||||
is WcEthMethod.SignTypedData -> method.account
|
||||
is WcEthMethod.AddEthereumChain -> walletManagerAddress
|
||||
is WcEthMethod.AddEthereumChain ->
|
||||
anyExistNetwork()
|
||||
?.let { network -> walletManagersFacade.getDefaultAddress(wallet.walletId, network).orEmpty() }
|
||||
.orEmpty()
|
||||
}
|
||||
val walletNetwork = when (method) {
|
||||
is WcEthMethod.SignTypedData,
|
||||
is WcEthMethod.MessageSign,
|
||||
is WcEthMethod.SendTransaction,
|
||||
is WcEthMethod.SignTransaction,
|
||||
-> networksConverter.findWalletNetworkForRequest(request, session, accountAddress)
|
||||
is WcEthMethod.AddEthereumChain -> anyExistNetwork()
|
||||
} ?: return null
|
||||
|
||||
val context = WcMethodUseCaseContext(
|
||||
session = session,
|
||||
rawSdkRequest = request,
|
||||
network = network,
|
||||
network = walletNetwork,
|
||||
accountAddress = accountAddress,
|
||||
)
|
||||
return when (method) {
|
||||
|
|
@ -62,7 +77,7 @@ internal class WcEthNetwork(
|
|||
}
|
||||
}
|
||||
|
||||
private fun WcEthMethodName.toMethod(request: WcSdkSessionRequest, wallet: UserWallet): WcEthMethod? {
|
||||
private suspend fun WcEthMethodName.toMethod(request: WcSdkSessionRequest, wallet: UserWallet): WcEthMethod? {
|
||||
val rawParams = request.request.params
|
||||
return when (this) {
|
||||
WcEthMethodName.EthSign,
|
||||
|
|
@ -85,8 +100,8 @@ internal class WcEthNetwork(
|
|||
WcEthMethodName.AddEthereumChain -> moshi.fromJson<List<WcEthAddChain>>(rawParams)
|
||||
?.firstOrNull()
|
||||
?.let {
|
||||
val newNetwork = namespaceConverter
|
||||
.toNetwork(it.chainId, wallet) ?: return null
|
||||
val newNetwork = networksConverter.mainOrAnyWalletNetworkForRequest(it.chainId, wallet)
|
||||
?: return null
|
||||
WcEthMethod.AddEthereumChain(rawChain = it, network = newNetwork)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,4 +16,7 @@ internal data class WcSolanaSignMessageRequest(
|
|||
internal data class WcSolanaSignTransactionRequest(
|
||||
@Json(name = "transaction")
|
||||
val transaction: String,
|
||||
|
||||
@Json(name = "feePayer")
|
||||
val feePayer: String?,
|
||||
)
|
||||
|
|
@ -6,14 +6,14 @@ import com.tangem.blockchain.extensions.decodeBase58
|
|||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.data.walletconnect.model.CAIP2
|
||||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter
|
||||
import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter.Companion.fromJson
|
||||
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.data.walletconnect.utils.WcNetworksConverter
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.data.walletconnect.model.CAIP2
|
||||
import com.tangem.domain.walletconnect.model.WcSolanaMethod
|
||||
import com.tangem.domain.walletconnect.model.WcSolanaMethodName
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
|
|
@ -21,13 +21,12 @@ import com.tangem.domain.walletconnect.repository.WcSessionsManager
|
|||
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import jakarta.inject.Inject
|
||||
import timber.log.Timber
|
||||
|
||||
internal class WcSolanaNetwork(
|
||||
private val moshi: Moshi,
|
||||
private val sessionsManager: WcSessionsManager,
|
||||
private val factories: Factories,
|
||||
private val namespaceConverter: NamespaceConverter,
|
||||
private val networksConverter: WcNetworksConverter,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
) : WcRequestToUseCaseConverter {
|
||||
|
||||
|
|
@ -37,17 +36,33 @@ internal class WcSolanaNetwork(
|
|||
return name
|
||||
}
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
override suspend fun toUseCase(request: WcSdkSessionRequest): WcMethodUseCase? {
|
||||
val name = toWcMethodName(request) ?: return null
|
||||
val method: WcSolanaMethod = name.toMethod(request) ?: return null
|
||||
val session = sessionsManager.findSessionByTopic(request.topic) ?: return null
|
||||
val network = namespaceConverter.toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null
|
||||
val accountAddress = getAccountAddress(session, network)
|
||||
val wallet = session.wallet
|
||||
val chainId = request.chainId.orEmpty()
|
||||
suspend fun anyExistNetwork() = networksConverter.mainOrAnyWalletNetworkForRequest(chainId, wallet)
|
||||
suspend fun anyAddress() = anyExistNetwork()
|
||||
?.let { network -> walletManagersFacade.getDefaultAddress(wallet.walletId, network).orEmpty() }
|
||||
.orEmpty()
|
||||
|
||||
val accountAddress = when (method) {
|
||||
is WcSolanaMethod.SignAllTransaction -> anyAddress()
|
||||
is WcSolanaMethod.SignMessage -> anyAddress()
|
||||
is WcSolanaMethod.SignTransaction -> method.address ?: anyAddress()
|
||||
}
|
||||
val walletNetwork = networksConverter
|
||||
.findWalletNetworkForRequest(request, session, accountAddress)
|
||||
?: anyExistNetwork()
|
||||
?: return null
|
||||
|
||||
val context = WcMethodUseCaseContext(
|
||||
session = session,
|
||||
rawSdkRequest = request,
|
||||
network = network,
|
||||
accountAddress = accountAddress.orEmpty(),
|
||||
network = walletNetwork,
|
||||
accountAddress = accountAddress,
|
||||
)
|
||||
return when (method) {
|
||||
is WcSolanaMethod.SignMessage -> factories.messageSign.create(context, method)
|
||||
|
|
@ -56,15 +71,6 @@ internal class WcSolanaNetwork(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun getAccountAddress(session: WcSession, network: Network): String? {
|
||||
return try {
|
||||
walletManagersFacade.getDefaultAddress(session.wallet.walletId, network)
|
||||
} catch (exception: Exception) {
|
||||
Timber.e(exception)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
internal class NamespaceConverter @Inject constructor(
|
||||
override val excludedBlockchains: ExcludedBlockchains,
|
||||
) : WcNamespaceConverter {
|
||||
|
|
@ -107,7 +113,7 @@ internal class WcSolanaNetwork(
|
|||
)
|
||||
}
|
||||
WcSolanaMethodName.SignTransaction -> moshi.fromJson<WcSolanaSignTransactionRequest>(rawParams)
|
||||
?.let { request -> WcSolanaMethod.SignTransaction(request.transaction) }
|
||||
?.let { request -> WcSolanaMethod.SignTransaction(request.transaction, request.feePayer) }
|
||||
WcSolanaMethodName.SendAllTransaction -> moshi.fromJson<List<String>>(rawParams)?.let { list ->
|
||||
WcSolanaMethod.SignAllTransaction(list)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package com.tangem.data.walletconnect.pair
|
|||
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.reown.walletkit.client.Wallet.Model.Namespace
|
||||
import com.tangem.data.common.currency.isCustomCoin
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
|
|
@ -25,16 +24,6 @@ internal class AssociateNetworksDelegate(
|
|||
private val tokensFeatureToggles: TokensFeatureToggles,
|
||||
) {
|
||||
|
||||
suspend fun associate(wallet: UserWallet, namespaces: Map<String, Namespace.Session>): Set<Network> {
|
||||
val walletNetworks = getWalletNetworks(userWalletId = wallet.walletId)
|
||||
val namespacesSet = namespaces.values.flatMap { proposal -> proposal.chains ?: listOf() }.toSet()
|
||||
return namespacesSet.mapNotNullTo(mutableSetOf()) { chainId ->
|
||||
val wcNetwork = namespaceConverters
|
||||
.firstNotNullOfOrNull { it.toNetwork(chainId, wallet) } ?: return@mapNotNullTo null
|
||||
walletNetworks.find { network -> wcNetwork.id == network.id }
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(WcPairError.UnsupportedBlockchains::class)
|
||||
suspend fun associate(sessionProposal: Wallet.Model.SessionProposal): Map<UserWallet, ProposalNetwork> {
|
||||
val userWallets = getWallets.invokeSync().filter { it.isMultiCurrency }
|
||||
|
|
@ -70,9 +59,9 @@ internal class AssociateNetworksDelegate(
|
|||
unknownRequired.add(missingNetworkName(chainId))
|
||||
return@forEach
|
||||
}
|
||||
val walletNetwork = walletNetworks.find { network -> wcNetwork.id == network.id }
|
||||
val walletNetwork = walletNetworks.find { network -> wcNetwork.rawId == network.rawId }
|
||||
|
||||
if (walletNetwork == null || isCustomCoin(walletNetwork)) {
|
||||
if (walletNetwork == null) {
|
||||
missingRequired.add(wcNetwork)
|
||||
} else {
|
||||
required.add(walletNetwork)
|
||||
|
|
@ -84,8 +73,8 @@ internal class AssociateNetworksDelegate(
|
|||
unknownOptional.add(missingNetworkName(chainId))
|
||||
return@forEach
|
||||
}
|
||||
val walletNetwork = walletNetworks.find { network -> wcNetwork.id == network.id }
|
||||
if (walletNetwork != null && !isCustomCoin(walletNetwork)) {
|
||||
val walletNetwork = walletNetworks.find { network -> wcNetwork.rawId == network.rawId }
|
||||
if (walletNetwork != null) {
|
||||
available.add(walletNetwork)
|
||||
} else {
|
||||
notAdded.add(wcNetwork)
|
||||
|
|
@ -117,6 +106,8 @@ internal class AssociateNetworksDelegate(
|
|||
}
|
||||
.filterIsInstance<CryptoCurrency.Coin>()
|
||||
.map(CryptoCurrency.Coin::network)
|
||||
// flatten all derivation
|
||||
.distinctBy { it.rawId }
|
||||
}
|
||||
|
||||
private fun Map<String, Namespace.Proposal>.setOfChainId(): Set<String> =
|
||||
|
|
|
|||
|
|
@ -1,48 +1,47 @@
|
|||
package com.tangem.data.walletconnect.pair
|
||||
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.tangem.data.walletconnect.model.CAIP10
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.data.walletconnect.utils.WcNetworksConverter
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.data.walletconnect.model.CAIP10
|
||||
import com.tangem.domain.walletconnect.model.WcSessionApprove
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
internal class CaipNamespaceDelegate(
|
||||
private val namespaceConverters: Set<WcNamespaceConverter>,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val wcNetworksConverter: WcNetworksConverter,
|
||||
) {
|
||||
|
||||
suspend fun associate(
|
||||
sessionProposal: Wallet.Model.SessionProposal,
|
||||
userWallet: UserWallet,
|
||||
networks: List<Network>,
|
||||
sessionForApprove: WcSessionApprove,
|
||||
): Map<String, Wallet.Model.Namespace.Session> {
|
||||
val userWallet = sessionForApprove.wallet
|
||||
val result = mutableMapOf<String, Session>()
|
||||
|
||||
networks.map { network ->
|
||||
val address = walletManagersFacade.getDefaultAddress(userWallet.walletId, network)
|
||||
val chainId = namespaceConverters.firstNotNullOfOrNull { it.toCAIP2(network) }
|
||||
requireNotNull(chainId)
|
||||
requireNotNull(address)
|
||||
CAIP10(chainId = chainId, accountAddress = address)
|
||||
}.forEach { account ->
|
||||
val namespaceKey = account.chainId.namespace
|
||||
val session = result.getOrPut(namespaceKey) { Session() }
|
||||
val requiredNamespaces = sessionProposal.requiredNamespaces
|
||||
val optionalNamespaces = sessionProposal.optionalNamespaces
|
||||
val methods = buildSet {
|
||||
requiredNamespaces[namespaceKey]?.methods?.let { addAll(it) }
|
||||
optionalNamespaces[namespaceKey]?.methods?.let { addAll(it) }
|
||||
wcNetworksConverter.convertNetworksForApprove(sessionForApprove)
|
||||
.mapNotNull { createCAIP10(userWallet.walletId, it) }
|
||||
.forEach { account ->
|
||||
val namespaceKey = account.chainId.namespace
|
||||
val session = result.getOrPut(namespaceKey) { Session() }
|
||||
val requiredNamespaces = sessionProposal.requiredNamespaces
|
||||
val optionalNamespaces = sessionProposal.optionalNamespaces
|
||||
val methods = buildSet {
|
||||
requiredNamespaces[namespaceKey]?.methods?.let { addAll(it) }
|
||||
optionalNamespaces[namespaceKey]?.methods?.let { addAll(it) }
|
||||
}
|
||||
val events = buildSet {
|
||||
requiredNamespaces[namespaceKey]?.events?.let { addAll(it) }
|
||||
optionalNamespaces[namespaceKey]?.events?.let { addAll(it) }
|
||||
}
|
||||
session.chains.add(account.chainId.raw)
|
||||
session.accounts.add(account.raw)
|
||||
session.methods.addAll(methods)
|
||||
session.events.addAll(events)
|
||||
}
|
||||
val events = buildSet {
|
||||
requiredNamespaces[namespaceKey]?.events?.let { addAll(it) }
|
||||
optionalNamespaces[namespaceKey]?.events?.let { addAll(it) }
|
||||
}
|
||||
session.chains.add(account.chainId.raw)
|
||||
session.accounts.add(account.raw)
|
||||
session.methods.addAll(methods)
|
||||
session.events.addAll(events)
|
||||
}
|
||||
return result.mapValues { (_, session) ->
|
||||
Wallet.Model.Namespace.Session(
|
||||
chains = session.chains.toList(),
|
||||
|
|
@ -53,6 +52,13 @@ internal class CaipNamespaceDelegate(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun createCAIP10(userWalletId: UserWalletId, network: Network): CAIP10? {
|
||||
val address = walletManagersFacade.getDefaultAddress(userWalletId, network)
|
||||
val chainId = namespaceConverters.firstNotNullOfOrNull { it.toCAIP2(network) }
|
||||
if (chainId == null || address == null) return null
|
||||
return CAIP10(chainId = chainId, accountAddress = address)
|
||||
}
|
||||
|
||||
private data class Session(
|
||||
val chains: MutableSet<String> = mutableSetOf(),
|
||||
val accounts: MutableSet<String> = mutableSetOf(),
|
||||
|
|
|
|||
|
|
@ -136,8 +136,7 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
): Either<WcPairError, Wallet.Model.SettledSessionResponse.Result> {
|
||||
val namespaces = caipNamespaceDelegate.associate(
|
||||
sdkSessionProposal,
|
||||
sessionForApprove.wallet,
|
||||
sessionForApprove.network,
|
||||
sessionForApprove,
|
||||
)
|
||||
val sessionApprove = Wallet.Params.SessionApprove(
|
||||
proposerPublicKey = sdkSessionProposal.proposerPublicKey,
|
||||
|
|
|
|||
|
|
@ -7,10 +7,7 @@ import com.domain.blockaid.models.dapp.CheckDAppResult
|
|||
import com.reown.walletkit.client.Wallet
|
||||
import com.reown.walletkit.client.WalletKit
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.walletconnect.pair.AssociateNetworksDelegate
|
||||
import com.tangem.data.walletconnect.utils.WC_TAG
|
||||
import com.tangem.data.walletconnect.utils.WcSdkObserver
|
||||
import com.tangem.data.walletconnect.utils.WcSdkSessionConverter
|
||||
import com.tangem.data.walletconnect.utils.*
|
||||
import com.tangem.datasource.local.walletconnect.WalletConnectStore
|
||||
import com.tangem.domain.walletconnect.WcAnalyticEvents
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
|
|
@ -33,7 +30,7 @@ internal class DefaultWcSessionsManager(
|
|||
private val legacyStore: WalletConnectSessionsRepository,
|
||||
private val getWallets: GetWalletsUseCase,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val associateNetworks: AssociateNetworksDelegate,
|
||||
private val wcNetworksConverter: WcNetworksConverter,
|
||||
private val analytics: AnalyticsEventHandler,
|
||||
private val scope: CoroutineScope,
|
||||
) : WcSessionsManager, WcSdkObserver {
|
||||
|
|
@ -85,20 +82,9 @@ internal class DefaultWcSessionsManager(
|
|||
}
|
||||
|
||||
override suspend fun findSessionByTopic(topic: String): WcSession? = withContext(dispatchers.io) {
|
||||
val storedSession = sessions.firstOrNull()
|
||||
sessions.firstOrNull()
|
||||
?.values?.flatten()
|
||||
?.firstOrNull { it.sdkModel.topic == topic }
|
||||
?: return@withContext null
|
||||
val sdkSession = WalletKit.getActiveSessionByTopic(topic) ?: return@withContext null
|
||||
val wallet = storedSession.wallet
|
||||
val networks = associateNetworks.associate(wallet, sdkSession.namespaces)
|
||||
WcSession(
|
||||
wallet = wallet,
|
||||
sdkModel = WcSdkSessionConverter.convert(sdkSession),
|
||||
securityStatus = storedSession.securityStatus,
|
||||
networks = networks,
|
||||
connectingTime = storedSession.connectingTime,
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSessionDelete(sessionDelete: Wallet.Model.SessionDelete) {
|
||||
|
|
@ -137,16 +123,16 @@ internal class DefaultWcSessionsManager(
|
|||
inStore: Set<WcSessionDTO>,
|
||||
wallets: List<UserWallet>,
|
||||
): List<WcSession> {
|
||||
val wcSessions = inStore.mapNotNull { session ->
|
||||
val wallet = wallets.find { it.walletId == session.walletId } ?: return@mapNotNull null
|
||||
val sdkSession = inSdk.find { it.topic == session.topic } ?: return@mapNotNull null
|
||||
val networks = associateNetworks.associate(wallet, sdkSession.namespaces)
|
||||
val wcSessions = inStore.mapNotNull { storeSession ->
|
||||
val wallet = wallets.find { it.walletId == storeSession.walletId } ?: return@mapNotNull null
|
||||
val sdkSession = inSdk.find { it.topic == storeSession.topic } ?: return@mapNotNull null
|
||||
val networks = wcNetworksConverter.findWalletNetworks(wallet, sdkSession)
|
||||
WcSession(
|
||||
wallet = wallet,
|
||||
sdkModel = WcSdkSessionConverter.convert(sdkSession),
|
||||
securityStatus = session.securityStatus,
|
||||
securityStatus = storeSession.securityStatus,
|
||||
networks = networks,
|
||||
connectingTime = session.connectingTime,
|
||||
connectingTime = storeSession.connectingTime,
|
||||
)
|
||||
}
|
||||
return wcSessions
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ package com.tangem.data.walletconnect.utils
|
|||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.data.common.network.NetworkFactory
|
||||
import com.tangem.data.walletconnect.model.CAIP2
|
||||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.data.walletconnect.model.CAIP2
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
internal interface WcNamespaceConverter {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
package com.tangem.data.walletconnect.utils
|
||||
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.tangem.data.common.currency.isCustomCoin
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.data.walletconnect.model.CAIP10
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.model.WcSessionApprove
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class WcNetworksConverter @Inject constructor(
|
||||
private val namespaceConverters: Set<WcNamespaceConverter>,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
private val tokensFeatureToggles: TokensFeatureToggles,
|
||||
) {
|
||||
|
||||
suspend fun findWalletNetworkForRequest(
|
||||
request: WcSdkSessionRequest,
|
||||
session: WcSession,
|
||||
requestAddress: String,
|
||||
): Network? {
|
||||
val wallet = session.wallet
|
||||
val allCoinNetwork = filterWalletNetworkForRequest(request.chainId.orEmpty(), session.wallet)
|
||||
|
||||
val requestNetwork = allCoinNetwork.find { network ->
|
||||
val address = walletManagersFacade.getDefaultAddress(wallet.walletId, network)
|
||||
requestAddress == address
|
||||
}
|
||||
return requestNetwork
|
||||
}
|
||||
|
||||
/**
|
||||
* return network with not custom derivationPath or first custom or any
|
||||
*/
|
||||
suspend fun mainOrAnyWalletNetworkForRequest(rawChainId: String, wallet: UserWallet): Network? {
|
||||
val networks = filterWalletNetworkForRequest(rawChainId, wallet)
|
||||
return networks.firstOrNull { !isCustomCoin(it) } ?: networks.firstOrNull()
|
||||
}
|
||||
|
||||
/**
|
||||
* return all exist derivation networks
|
||||
*/
|
||||
suspend fun filterWalletNetworkForRequest(rawChainId: String, wallet: UserWallet): List<Network> {
|
||||
val walletNetworks = getWalletNetworks(wallet.walletId)
|
||||
|
||||
val blockchain = namespaceConverters
|
||||
.firstNotNullOfOrNull { it.toBlockchain(rawChainId) } ?: return listOf()
|
||||
|
||||
val allCoinNetwork = walletNetworks.filter { it.rawId == blockchain.id }
|
||||
return allCoinNetwork
|
||||
}
|
||||
|
||||
suspend fun findWalletNetworks(wallet: UserWallet, sdkSession: Wallet.Model.Session): Set<Network> {
|
||||
val walletNetworks = getWalletNetworks(wallet.walletId)
|
||||
val existNetworks = sdkSession.namespaces.values
|
||||
.map { it.accounts }.flatten().toSet()
|
||||
.mapNotNull { CAIP10.fromRaw(it) }
|
||||
.mapNotNullTo(mutableSetOf()) { caip10 ->
|
||||
val blockchain = namespaceConverters
|
||||
.firstNotNullOfOrNull { it.toBlockchain(caip10.chainId) }
|
||||
?: return@mapNotNullTo null
|
||||
walletNetworks
|
||||
// find all derivation
|
||||
.filter { it.rawId == blockchain.id }
|
||||
// find equal address
|
||||
.firstOrNull {
|
||||
val walletAddress = walletManagersFacade.getDefaultAddress(wallet.walletId, it)
|
||||
walletAddress == caip10.accountAddress
|
||||
}
|
||||
}
|
||||
|
||||
return existNetworks
|
||||
}
|
||||
|
||||
suspend fun convertNetworksForApprove(sessionForApprove: WcSessionApprove): List<Network> {
|
||||
val walletNetworks = getWalletNetworks(sessionForApprove.wallet.walletId)
|
||||
return sessionForApprove.network
|
||||
.map { network -> walletNetworks.filter { walletNetwork -> walletNetwork.rawId == network.rawId } }
|
||||
.flatten()
|
||||
}
|
||||
|
||||
private suspend fun getWalletNetworks(userWalletId: UserWalletId): List<Network> {
|
||||
return if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
|
||||
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
|
||||
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId),
|
||||
).orEmpty()
|
||||
} else {
|
||||
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
|
||||
}.filterIsInstance<CryptoCurrency.Coin>().map(CryptoCurrency.Coin::network)
|
||||
}
|
||||
}
|
||||
|
|
@ -114,8 +114,7 @@ internal class DefaultWcPairUseCaseTest {
|
|||
coEvery {
|
||||
caipNamespaceDelegate.associate(
|
||||
sessionProposal = sdkProposal,
|
||||
userWallet = sessionForApprove.wallet,
|
||||
networks = sessionForApprove.network,
|
||||
sessionForApprove = sessionForApprove,
|
||||
)
|
||||
} returns mapOf()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue