Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-10 16:47:17 +03:00
commit 5fa587d8cc
635 changed files with 18802 additions and 9118 deletions

View file

@ -21,12 +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.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.walletconnect.WcPairService
import com.tangem.domain.walletconnect.WcRequestService
import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
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.usecase.disconnect.WcDisconnectUseCase
@ -90,7 +87,6 @@ internal object WalletConnectDataModule {
fun defaultWcSessionsManager(
store: WalletConnectStore,
dispatchers: CoroutineDispatcherProvider,
legacyStore: WalletConnectSessionsRepository,
getWallets: GetWalletsUseCase,
wcNetworksConverter: WcNetworksConverter,
analytics: AnalyticsEventHandler,
@ -99,7 +95,6 @@ internal object WalletConnectDataModule {
return DefaultWcSessionsManager(
store = store,
dispatchers = dispatchers,
legacyStore = legacyStore,
getWallets = getWallets,
wcNetworksConverter = wcNetworksConverter,
analytics = analytics,
@ -177,15 +172,11 @@ internal object WalletConnectDataModule {
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
@ -193,15 +184,11 @@ internal object WalletConnectDataModule {
fun associateNetworksDelegate(
namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>,
getWallets: GetWalletsUseCase,
currenciesRepository: CurrenciesRepository,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): AssociateNetworksDelegate = AssociateNetworksDelegate(
namespaceConverters = namespaceConverters,
getWallets = getWallets,
currenciesRepository = currenciesRepository,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
@Provides

View file

@ -10,8 +10,6 @@ import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.isMultiCurrency
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.domain.walletconnect.model.WcPairError
import com.tangem.domain.walletconnect.model.WcSessionProposal.ProposalNetwork
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
@ -19,9 +17,7 @@ import com.tangem.domain.wallets.usecase.GetWalletsUseCase
internal class AssociateNetworksDelegate(
private val namespaceConverters: Set<WcNamespaceConverter>,
private val getWallets: GetWalletsUseCase,
private val currenciesRepository: CurrenciesRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
@Throws(WcPairError.UnsupportedBlockchains::class)
@ -96,14 +92,10 @@ internal class AssociateNetworksDelegate(
}
private suspend fun getWalletNetworks(userWalletId: UserWalletId): List<Network> {
return if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId),
)
.orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
}
return multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId),
)
.orEmpty()
.filterIsInstance<CryptoCurrency.Coin>()
.map(CryptoCurrency.Coin::network)
// flatten all derivation

View file

@ -3,7 +3,6 @@ package com.tangem.data.walletconnect.sessions
import arrow.core.Either
import arrow.core.left
import arrow.core.right
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
@ -16,7 +15,6 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.walletconnect.WcAnalyticEvents
import com.tangem.domain.walletconnect.model.WcSession
import com.tangem.domain.walletconnect.model.WcSessionDTO
import com.tangem.domain.walletconnect.model.legacy.WalletConnectSessionsRepository
import com.tangem.domain.walletconnect.repository.WcSessionsManager
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -30,7 +28,6 @@ import kotlin.coroutines.resume
@Suppress("LongParameterList")
internal class DefaultWcSessionsManager(
private val store: WalletConnectStore,
private val legacyStore: WalletConnectSessionsRepository,
private val getWallets: GetWalletsUseCase,
private val dispatchers: CoroutineDispatcherProvider,
private val wcNetworksConverter: WcNetworksConverter,
@ -39,18 +36,12 @@ internal class DefaultWcSessionsManager(
) : WcSessionsManager, WcSdkObserver {
private val onSessionDelete = Channel<Wallet.Model.SessionDelete>(capacity = Channel.BUFFERED)
private val oneTimeMigration = MutableStateFlow(true)
override val sessions: Flow<Map<UserWallet, List<WcSession>>>
get() = combine(getWallets(), store.sessions) { wallets, inStore -> wallets to inStore }
.transform { pair ->
val (wallets, inStore) = pair
val inSdk: List<Wallet.Model.Session> = WalletKit.getListOfActiveSessions()
if (oneTimeMigration.value) {
oneTimeMigration.value = false
val someMigrated = migrateLegacyStore(inStore, inSdk, wallets)
if (someMigrated) return@transform // ignore emit, wait next one
}
val associatedSessions: List<WcSession> = associate(inSdk, inStore, wallets)
val someRemove = removeUnknownSessions(inStore, inSdk, associatedSessions)
if (someRemove) return@transform // ignore emit, wait next one
@ -60,7 +51,6 @@ internal class DefaultWcSessionsManager(
.flowOn(dispatchers.io)
override fun onWcSdkInit() {
oneTimeMigration.value = true
listenOnSessionDelete()
extendSessions()
}
@ -96,39 +86,6 @@ internal class DefaultWcSessionsManager(
onSessionDelete.trySend(sessionDelete)
}
private suspend fun migrateLegacyStore(
inNewStore: Set<WcSessionDTO>,
inSdk: List<Wallet.Model.Session>,
wallets: List<UserWallet>,
): Boolean {
val walletIds = wallets.map { wallet -> wallet.walletId }
val inLegacyStore = walletIds
.map { walletId ->
flow {
emit(
legacyStore.loadSessions(walletId.stringValue).mapNotNull { legacySession ->
val url =
inSdk.find { it.topic == legacySession.topic }?.metaData?.url ?: return@mapNotNull null
WcSessionDTO(
topic = legacySession.topic,
walletId = walletId,
url = url,
securityStatus = CheckDAppResult.FAILED_TO_VERIFY,
)
},
)
}
}
.merge()
.reduce { accumulator, value -> accumulator.plus(value) }
// migrate only active legacySessions
.filter { legacySession -> inSdk.any { inSdkSession -> inSdkSession.topic == legacySession.topic } }
val mustSaveInNewStore = inLegacyStore.subtract(inNewStore)
if (mustSaveInNewStore.isNotEmpty()) store.saveSessions(mustSaveInNewStore)
return mustSaveInNewStore.isNotEmpty()
}
private suspend fun associate(
inSdk: List<Wallet.Model.Session>,
inStore: Set<WcSessionDTO>,

View file

@ -9,8 +9,6 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
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.domain.walletconnect.model.WcSession
import com.tangem.domain.walletconnect.model.WcSessionApprove
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
@ -20,9 +18,7 @@ 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,
) {
fun createNetwork(chainId: String, wallet: UserWallet): Network? {
@ -101,12 +97,10 @@ internal class WcNetworksConverter @Inject constructor(
}
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)
return multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId),
)
.orEmpty()
.filterIsInstance<CryptoCurrency.Coin>().map(CryptoCurrency.Coin::network)
}
}