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 b0012d93a3..ef493b58ff 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 @@ -22,7 +22,6 @@ import com.tangem.datasource.di.SdkMoshi import com.tangem.datasource.local.walletconnect.WalletConnectStore import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.account.supplier.MultiAccountListSupplier -import com.tangem.domain.account.supplier.SingleAccountSupplier import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.walletconnect.WcPairService import com.tangem.domain.walletconnect.WcRequestService @@ -92,6 +91,7 @@ internal object WalletConnectDataModule { dispatchers: CoroutineDispatcherProvider, getWallets: GetWalletsUseCase, wcNetworksConverter: WcNetworksConverter, + multiAccountListSupplier: MultiAccountListSupplier, analytics: AnalyticsEventHandler, wcScope: WcScope, ): DefaultWcSessionsManager { @@ -102,6 +102,7 @@ internal object WalletConnectDataModule { wcNetworksConverter = wcNetworksConverter, analytics = analytics, scope = wcScope, + multiAccountListSupplier = multiAccountListSupplier, ) } @@ -181,12 +182,10 @@ internal object WalletConnectDataModule { namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>, walletManagersFacade: WalletManagersFacade, singleAccountStatusListSupplier: SingleAccountStatusListSupplier, - singleAccountSupplier: SingleAccountSupplier, ): WcNetworksConverter = WcNetworksConverter( namespaceConverters = namespaceConverters, walletManagersFacade = walletManagersFacade, singleAccountStatusListSupplier = singleAccountStatusListSupplier, - singleAccountSupplier = singleAccountSupplier, ) @Provides 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 96a3982807..c6b1625126 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 @@ -6,10 +6,17 @@ import arrow.core.right import com.reown.walletkit.client.Wallet import com.reown.walletkit.client.WalletKit import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.data.walletconnect.utils.* +import com.tangem.data.walletconnect.utils.WC_TAG +import com.tangem.data.walletconnect.utils.WcNetworksConverter +import com.tangem.data.walletconnect.utils.WcScope +import com.tangem.data.walletconnect.utils.WcSdkObserver +import com.tangem.data.walletconnect.utils.WcSdkSessionConverter import com.tangem.datasource.local.walletconnect.WalletConnectStore +import com.tangem.domain.account.models.AccountList +import com.tangem.domain.account.supplier.MultiAccountListSupplier import com.tangem.domain.models.account.Account import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.walletconnect.WcAnalyticEvents import com.tangem.domain.walletconnect.model.WcSession import com.tangem.domain.walletconnect.model.WcSessionDTO @@ -28,7 +35,8 @@ import kotlin.coroutines.resume @Suppress("LongParameterList") internal class DefaultWcSessionsManager( private val store: WalletConnectStore, - private val getWallets: GetWalletsUseCase, + getWallets: GetWalletsUseCase, + multiAccountListSupplier: MultiAccountListSupplier, private val dispatchers: CoroutineDispatcherProvider, private val wcNetworksConverter: WcNetworksConverter, private val analytics: AnalyticsEventHandler, @@ -37,18 +45,31 @@ internal class DefaultWcSessionsManager( private val onSessionDelete = Channel(capacity = Channel.BUFFERED) - override val sessions: Flow>> - get() = combine(getWallets(), store.sessions) { wallets, inStore -> wallets to inStore } - .transform { pair -> - val (wallets, inStore) = pair - val inSdk: List = WalletKit.getListOfActiveSessions() - val associatedSessions: List = associate(inSdk, inStore, wallets) - val someRemove = removeUnknownSessions(inStore, inSdk, associatedSessions) - if (someRemove) return@transform // ignore emit, wait next one - emit(associatedSessions.groupBy { it.wallet }) - } - .distinctUntilChanged() - .flowOn(dispatchers.io) + override val sessions: Flow>> = combine( + flow = getWallets(), + flow2 = store.sessions, + flow3 = multiAccountListSupplier.invokeMap(), + transform = ::Triple, + ) + .transformLatest { triple -> + val (wallets, inStore, allWalletsAccounts) = triple + val inSdk: List = WalletKit.getListOfActiveSessions() + val associatedSessions: List = associate( + inSdk = inSdk, + inStore = inStore, + wallets = wallets, + allWalletsAccounts = allWalletsAccounts, + ) + removeUnknownSessions(inStore, inSdk, associatedSessions) + emit(associatedSessions.groupBy { it.wallet }) + } + .distinctUntilChanged() + .flowOn(dispatchers.io) + .shareIn( + scope = scope, + started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 0, replayExpirationMillis = 0), + replay = 1, + ) override fun onWcSdkInit() { listenOnSessionDelete() @@ -78,6 +99,7 @@ internal class DefaultWcSessionsManager( inSdk: List, inStore: Set, wallets: List, + allWalletsAccounts: LinkedHashMap, ): List { // if the WcSdk `onSessionSettleResponse` callback arrives late, merge pending approvals with WcSdk sessions val savedPending = store.pendingApproval.first() @@ -91,7 +113,9 @@ internal class DefaultWcSessionsManager( val wcSessions = savedPending.plus(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 account = wcNetworksConverter.getAccount(storeSession.accountId) as? Account.CryptoPortfolio + val walletAccounts = allWalletsAccounts[storeSession.walletId] ?: return@mapNotNull null + val account = walletAccounts.accounts + .find { account -> account.accountId == storeSession.accountId } as? Account.CryptoPortfolio ?: return@mapNotNull null val networks = wcNetworksConverter.findWalletNetworks(wallet, account, sdkSession) val originUrl = storeSession.url ?: sdkSession.metaData?.url ?: "" diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNetworksConverter.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNetworksConverter.kt index 9104712d62..8ef4d7a69e 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNetworksConverter.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/utils/WcNetworksConverter.kt @@ -6,10 +6,8 @@ import com.tangem.blockchain.common.address.AddressType import com.tangem.blockchainsdk.utils.toBlockchain import com.tangem.data.common.currency.isCustomCoin import com.tangem.data.walletconnect.model.CAIP10 -import com.tangem.domain.account.producer.SingleAccountProducer import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier -import com.tangem.domain.account.supplier.SingleAccountSupplier import com.tangem.domain.models.account.Account import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.account.AccountStatus @@ -28,7 +26,6 @@ internal class WcNetworksConverter @Inject constructor( private val namespaceConverters: Set, private val walletManagersFacade: WalletManagersFacade, private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, - private val singleAccountSupplier: SingleAccountSupplier, ) { fun createNetwork(chainId: String, wallet: UserWallet): Network? { @@ -117,10 +114,6 @@ internal class WcNetworksConverter @Inject constructor( return existNetworks } - suspend fun getAccount(accountId: AccountId): Account? { - return singleAccountSupplier.getSyncOrNull(SingleAccountProducer.Params(accountId)) - } - suspend fun convertNetworksForApprove(sessionForApprove: WcSessionApprove): List { val portfolioNetworks = getAccountNetworks(sessionForApprove.account.accountId) return sessionForApprove.network diff --git a/domain/account/src/main/java/com/tangem/domain/account/supplier/MultiAccountListSupplier.kt b/domain/account/src/main/java/com/tangem/domain/account/supplier/MultiAccountListSupplier.kt index 45989af478..a914d2b6f4 100644 --- a/domain/account/src/main/java/com/tangem/domain/account/supplier/MultiAccountListSupplier.kt +++ b/domain/account/src/main/java/com/tangem/domain/account/supplier/MultiAccountListSupplier.kt @@ -3,7 +3,9 @@ package com.tangem.domain.account.supplier import com.tangem.domain.account.models.AccountList import com.tangem.domain.account.producer.MultiAccountListProducer import com.tangem.domain.core.flow.FlowCachingSupplier +import com.tangem.domain.models.wallet.UserWalletId import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map /** * Supplier that provides a list of [AccountList]s for all user wallets. @@ -18,4 +20,12 @@ abstract class MultiAccountListSupplier( operator fun invoke(): Flow> { return super.invoke(params = Unit) } + + fun invokeMap(): Flow> = invoke() + .map { accountLists -> + accountLists.associateByTo( + destination = linkedMapOf(), + keySelector = { accountList -> accountList.userWalletId }, + ) + } } \ No newline at end of file