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 3ae3557cc0..b0012d93a3 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 @@ -24,7 +24,6 @@ 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.tokens.MultiWalletCryptoCurrenciesSupplier import com.tangem.domain.walletconnect.WcPairService import com.tangem.domain.walletconnect.WcRequestService import com.tangem.domain.walletconnect.WcRequestUseCaseFactory @@ -181,14 +180,12 @@ internal object WalletConnectDataModule { fun wcNetworksConverter( namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>, walletManagersFacade: WalletManagersFacade, - multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, singleAccountStatusListSupplier: SingleAccountStatusListSupplier, singleAccountSupplier: SingleAccountSupplier, ): WcNetworksConverter = WcNetworksConverter( namespaceConverters = namespaceConverters, walletManagersFacade = walletManagersFacade, singleAccountStatusListSupplier = singleAccountStatusListSupplier, - multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier, singleAccountSupplier = singleAccountSupplier, ) diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthAddNetworkUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthAddNetworkUseCase.kt index d835bc5139..22da45b6f4 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthAddNetworkUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthAddNetworkUseCase.kt @@ -131,12 +131,9 @@ internal class WcEthAddSwitchCommonDelegate @AssistedInject constructor( val caip2 = hexChainIdToCAIP2(hexChainId) ?: return HandleMethodError.UnknownError("Failed to parse CAIP2").left() val generalNetwork = networksConverter.createNetwork(caip2.raw, wallet) - if (generalNetwork == null) { - return HandleMethodError.TangemUnsupportedNetwork(caip2.raw).left() - } + ?: return HandleMethodError.TangemUnsupportedNetwork(caip2.raw).left() val addedNetwork = networksConverter.mainOrAnyWalletNetworkForRequest( rawChainId = caip2.raw, - wallet = wallet, account = context.session.account, ) if (addedNetwork == null) { diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt index c03d165fa0..a1d65ed85f 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/ethereum/WcEthNetwork.kt @@ -47,7 +47,6 @@ internal class WcEthNetwork( ?: return error("Failed to parse $name") suspend fun anyExistNetwork() = networksConverter.mainOrAnyWalletNetworkForRequest( rawChainId = chainId, - wallet = wallet, account = account, ) @@ -74,7 +73,7 @@ internal class WcEthNetwork( -> anyExistNetwork() } ?: return error("Failed to find walletNetwork for accountAddress $accountAddress") - val networkDerivationsCount = networksConverter.filterWalletNetworkForRequest(chainId, wallet, account).size + val networkDerivationsCount = networksConverter.filterWalletNetworkForRequest(chainId, account).size val context = WcMethodUseCaseContext( session = session, rawSdkRequest = request, diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt index bb68bd46d2..0265091789 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/network/solana/WcSolanaNetwork.kt @@ -49,7 +49,7 @@ internal class WcSolanaNetwork( val wallet = session.wallet val account = session.account val chainId = request.chainId.orEmpty() - suspend fun anyExistNetwork() = networksConverter.mainOrAnyWalletNetworkForRequest(chainId, wallet, account) + suspend fun anyExistNetwork() = networksConverter.mainOrAnyWalletNetworkForRequest(chainId, account) suspend fun anyAddress() = anyExistNetwork() ?.let { network -> networksConverter.getAddressForWC(wallet.walletId, network).orEmpty() } .orEmpty() @@ -64,7 +64,7 @@ internal class WcSolanaNetwork( ?: anyExistNetwork() ?: return error("Failed to find walletNetwork for accountAddress $accountAddress") - val networkDerivationsCount = networksConverter.filterWalletNetworkForRequest(chainId, wallet, account).size + val networkDerivationsCount = networksConverter.filterWalletNetworkForRequest(chainId, account).size val context = WcMethodUseCaseContext( session = session, rawSdkRequest = request, @@ -86,7 +86,7 @@ internal class WcSolanaNetwork( override val namespaceKey: NamespaceKey = NamespaceKey("solana") override fun toBlockchain(chainId: CAIP2): Blockchain? { - val isMainNet = MAINNET_CHAIN_ID.any { it.lowercase() == chainId.reference.lowercase() } + val isMainNet = MAINNET_CHAIN_ID.any { it.equals(chainId.reference, ignoreCase = true) } if (chainId.namespace != namespaceKey.key) return null return when { isMainNet -> Blockchain.Solana diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt index a1384944b8..c35cd5c848 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/AssociateNetworksDelegate.kt @@ -8,7 +8,6 @@ import com.tangem.domain.models.account.Account import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.isLocked import com.tangem.domain.models.wallet.isMultiCurrency import com.tangem.domain.walletconnect.model.WcPairError @@ -23,19 +22,6 @@ internal class AssociateNetworksDelegate( private val getWallets: GetWalletsUseCase, ) { - @Throws(WcPairError.UnsupportedBlockchains::class) - suspend fun associate(sessionProposal: Wallet.Model.SessionProposal): Map { - val userWallets = getWallets.invokeSync().filter { it.isMultiCurrency } - val requiredNamespaces: Set = sessionProposal.requiredNamespaces.setOfChainId() - val optionalNamespaces: Set = sessionProposal.optionalNamespaces.setOfChainId() - // remove duplicates - .subtract(requiredNamespaces) - - return userWallets.associateWith { wallet -> - mapNetworksForPortfolio(wallet, null, requiredNamespaces, optionalNamespaces, sessionProposal) - } - } - @Throws(WcPairError.UnsupportedBlockchains::class) suspend fun associateAccounts(sessionProposal: Wallet.Model.SessionProposal): Map { val userWallets = getWallets.invokeSync() @@ -67,13 +53,12 @@ internal class AssociateNetworksDelegate( @Suppress("CyclomaticComplexMethod") private suspend fun mapNetworksForPortfolio( wallet: UserWallet, - account: Account?, + account: Account, requiredNamespaces: Set, optionalNamespaces: Set, sessionProposal: Wallet.Model.SessionProposal, ): ProposalNetwork { - val portfolioNetworks = account?.let { getAccountNetworks(it.accountId) } - ?: getWalletNetworks(userWalletId = wallet.walletId) + val portfolioNetworks = getAccountNetworks(account.accountId) val unknownRequired = mutableSetOf() val unknownOptional = mutableSetOf() @@ -127,12 +112,6 @@ internal class AssociateNetworksDelegate( ) } - private suspend fun getWalletNetworks(userWalletId: UserWalletId): List { - return networksConverter.getWalletNetworks(userWalletId) - // flatten all derivation - .distinctBy { it.rawId } - } - private suspend fun getAccountNetworks(accountId: AccountId): List { return networksConverter.getAccountNetworks(accountId) // flatten all derivation 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 432700dc15..bf81785e59 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 @@ -111,7 +111,7 @@ internal class DefaultWcPairUseCase @AssistedInject constructor( val sessionDTO = WcSessionDTO( topic = "", walletId = sessionForApprove.wallet.walletId, - accountId = sessionForApprove.account?.accountId, + accountId = sessionForApprove.account.accountId, url = sdkVerifyContext.getDappOriginUrl(), securityStatus = proposalState.dAppSession.securityStatus, connectingTime = connectingTime, @@ -195,7 +195,6 @@ internal class DefaultWcPairUseCase @AssistedInject constructor( sessionProposal: Wallet.Model.SessionProposal, verifyContext: Wallet.Model.VerifyContext, ): Either = runCatching { - val proposalNetwork = associateNetworksDelegate.associate(sessionProposal) val proposalAccountNetwork = associateNetworksDelegate.associateAccounts(sessionProposal) val verificationInfo = when { verifyContext.validation == Wallet.Model.Validation.INVALID -> CheckDAppResult.UNSAFE @@ -224,7 +223,6 @@ internal class DefaultWcPairUseCase @AssistedInject constructor( ) val dAppSession = WcSessionProposal( dAppMetaData = appMetaData, - proposalNetwork = proposalNetwork, securityStatus = verificationInfo, proposalAccountNetwork = proposalAccountNetwork, ) 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 7967e2d59f..96a3982807 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 @@ -9,7 +9,6 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.data.walletconnect.utils.* import com.tangem.datasource.local.walletconnect.WalletConnectStore import com.tangem.domain.models.account.Account -import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.walletconnect.WcAnalyticEvents import com.tangem.domain.walletconnect.model.WcSession @@ -37,15 +36,12 @@ internal class DefaultWcSessionsManager( ) : WcSessionsManager, WcSdkObserver { private val onSessionDelete = Channel(capacity = Channel.BUFFERED) - private val oneTimeMigration = MutableStateFlow(false) 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 someMigrate = migrateToAccountSession(inStore) - if (someMigrate) return@transform val associatedSessions: List = associate(inSdk, inStore, wallets) val someRemove = removeUnknownSessions(inStore, inSdk, associatedSessions) if (someRemove) return@transform // ignore emit, wait next one @@ -54,25 +50,6 @@ internal class DefaultWcSessionsManager( .distinctUntilChanged() .flowOn(dispatchers.io) - private suspend fun migrateToAccountSession(inStore: Set): Boolean { - if (oneTimeMigration.value) return false - - var someMigrated = false - - val updatedSessions = inStore.mapTo(mutableSetOf()) { sessionDTO -> - if (sessionDTO.accountId == null) { - someMigrated = true - val mainAccountId = AccountId.forMainCryptoPortfolio(sessionDTO.walletId) - sessionDTO.copy(accountId = mainAccountId) - } else { - sessionDTO - } - } - if (someMigrated) store.saveSessions(updatedSessions) - oneTimeMigration.value = true - return someMigrated - } - override fun onWcSdkInit() { listenOnSessionDelete() extendSessions() @@ -114,7 +91,7 @@ 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 = storeSession.accountId?.let { wcNetworksConverter.getAccount(it) } as? Account.CryptoPortfolio + val account = wcNetworksConverter.getAccount(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/sign/WcSignUseCaseDelegate.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt index ebf56dafcf..d3c3d64bdf 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt @@ -71,7 +71,7 @@ internal class WcSignUseCaseDelegate( network = context.network, errorCode = error.code(), errorMessage = errorMessage, - accountDerivation = context.session.account?.derivationIndex?.value, + accountDerivation = context.session.account.derivationIndex.value, ) analytics.send(event) } 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 d4b19d974a..9104712d62 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 @@ -18,8 +18,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network 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.walletconnect.model.WcSession import com.tangem.domain.walletconnect.model.WcSessionApprove import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest @@ -31,7 +29,6 @@ internal class WcNetworksConverter @Inject constructor( private val walletManagersFacade: WalletManagersFacade, private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, private val singleAccountSupplier: SingleAccountSupplier, - private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, ) { fun createNetwork(chainId: String, wallet: UserWallet): Network? { @@ -47,13 +44,12 @@ internal class WcNetworksConverter @Inject constructor( val wallet = session.wallet val allCoinNetwork = filterWalletNetworkForRequest( rawChainId = request.chainId.orEmpty(), - wallet = session.wallet, account = session.account, ) val requestNetwork = allCoinNetwork.find { network -> val address = getAddressForWC(wallet.walletId, network) - requestAddress.lowercase() == address?.lowercase() + requestAddress.equals(address, ignoreCase = true) } return requestNetwork } @@ -61,13 +57,13 @@ internal class WcNetworksConverter @Inject constructor( /** * return network with not custom derivationPath or first custom or any */ - suspend fun mainOrAnyWalletNetworkForRequest(rawChainId: String, wallet: UserWallet, account: Account?): Network? { - val networks = filterWalletNetworkForRequest(rawChainId, wallet, account) + suspend fun mainOrAnyWalletNetworkForRequest(rawChainId: String, account: Account): Network? { + val networks = filterWalletNetworkForRequest(rawChainId, account) return networks.firstOrNull { !isCustomCoin(it) } ?: networks.firstOrNull() } - suspend fun allAddressForChain(rawChainId: String, wallet: UserWallet, account: Account?): List { - return filterWalletNetworkForRequest(rawChainId, wallet, account) + suspend fun allAddressForChain(rawChainId: String, wallet: UserWallet, account: Account): List { + return filterWalletNetworkForRequest(rawChainId, account) .mapNotNull { getAddressForWC(wallet.walletId, it)?.lowercase() } } @@ -85,13 +81,8 @@ internal class WcNetworksConverter @Inject constructor( /** * return all exist derivation networks */ - suspend fun filterWalletNetworkForRequest( - rawChainId: String, - wallet: UserWallet, - account: Account?, - ): List { - val portfolioNetworks = account?.let { getAccountNetworks(it.accountId) } - ?: getWalletNetworks(wallet.walletId) + suspend fun filterWalletNetworkForRequest(rawChainId: String, account: Account): List { + val portfolioNetworks = getAccountNetworks(account.accountId) val blockchain = namespaceConverters .firstNotNullOfOrNull { it.toBlockchain(rawChainId) } ?: return listOf() @@ -102,11 +93,10 @@ internal class WcNetworksConverter @Inject constructor( suspend fun findWalletNetworks( wallet: UserWallet, - account: Account?, + account: Account, sdkSession: Wallet.Model.Session, ): Set { - val portfolioNetworks = account?.let { getAccountNetworks(it.accountId) } - ?: getWalletNetworks(wallet.walletId) + val portfolioNetworks = getAccountNetworks(account.accountId) val existNetworks = sdkSession.namespaces.values .map { it.accounts }.flatten().toSet() .mapNotNull { CAIP10.fromRaw(it) } @@ -120,7 +110,7 @@ internal class WcNetworksConverter @Inject constructor( // find equal address .firstOrNull { network -> val walletAddress = getAddressForWC(wallet.walletId, network) - walletAddress?.lowercase() == caip10.accountAddress.lowercase() + walletAddress.equals(caip10.accountAddress, ignoreCase = true) } } @@ -132,21 +122,12 @@ internal class WcNetworksConverter @Inject constructor( } suspend fun convertNetworksForApprove(sessionForApprove: WcSessionApprove): List { - val portfolioNetworks = sessionForApprove.account?.let { getAccountNetworks(it.accountId) } - ?: getWalletNetworks(sessionForApprove.wallet.walletId) + val portfolioNetworks = getAccountNetworks(sessionForApprove.account.accountId) return sessionForApprove.network .map { network -> portfolioNetworks.filter { walletNetwork -> walletNetwork.rawId == network.rawId } } .flatten() } - suspend fun getWalletNetworks(userWalletId: UserWalletId): List { - return multiWalletCryptoCurrenciesSupplier.getSyncOrNull( - params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId), - ) - .orEmpty() - .filterIsInstance().map(CryptoCurrency.Coin::network) - } - private suspend fun getAccountStatus(accountId: AccountId): AccountStatus.CryptoPortfolio? { return singleAccountStatusListSupplier.getSyncOrNull( SingleAccountStatusListProducer.Params(accountId.userWalletId), 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 9d81be58d2..afaed251c9 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,6 +15,7 @@ import com.tangem.data.walletconnect.pair.DefaultWcPairUseCase import com.tangem.data.walletconnect.pair.WcPairSdkDelegate import com.tangem.data.walletconnect.utils.WcSdkSessionConverter import com.tangem.domain.blockaid.BlockAidVerifier +import com.tangem.domain.models.account.Account import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.walletconnect.model.WcPairError import com.tangem.domain.walletconnect.model.WcPairRequest @@ -73,7 +74,7 @@ internal class DefaultWcPairUseCaseTest { get() = WcSessionApprove( wallet = MockUserWalletFactory.create(), network = listOf(), - account = null, + account = Account.CryptoPortfolio.createMainAccount(MockUserWalletFactory.create().walletId), ) private val sdkApprove: Wallet.Params.SessionApprove @@ -106,7 +107,7 @@ internal class DefaultWcPairUseCaseTest { networks = setOf(), connectingTime = null, showWalletInfo = false, - account = null, + account = Account.CryptoPortfolio.createMainAccount(MockUserWalletFactory.create().walletId), ) private fun useCaseFactory() = DefaultWcPairUseCase( @@ -120,7 +121,6 @@ internal class DefaultWcPairUseCaseTest { @Before fun setup() { - coEvery { associateNetworksDelegate.associate(sdkProposal) } returns mapOf() coEvery { associateNetworksDelegate.associateAccounts(sdkProposal) } returns mapOf() coEvery { caipNamespaceDelegate.associate( @@ -254,7 +254,6 @@ internal class DefaultWcPairUseCaseTest { assertEquals(loading, awaitItem()) coVerifyOrder { sdkDelegate.pair(url) - associateNetworksDelegate.associate(sdkProposal) blockAidVerifier.verifyDApp(DAppData(sdkVerifyContext.origin)) } assert(awaitItem() is WcPairState.Proposal) diff --git a/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/WcSignUseCaseDelegateTest.kt b/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/WcSignUseCaseDelegateTest.kt index d703676123..069d84224c 100644 --- a/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/WcSignUseCaseDelegateTest.kt +++ b/data/wallet-connect/src/test/kotlin/com/tangem/domain/walletconnect/WcSignUseCaseDelegateTest.kt @@ -10,6 +10,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.data.walletconnect.sign.* import com.tangem.data.walletconnect.sign.SignStateConverter.toResult import com.tangem.data.walletconnect.sign.SignStateConverter.toSigning +import com.tangem.domain.models.account.Account import com.tangem.domain.walletconnect.model.WcRequestError import com.tangem.domain.walletconnect.model.WcSession import com.tangem.domain.walletconnect.model.sdkcopy.WcAppMetaData @@ -58,7 +59,7 @@ internal class WcSignUseCaseDelegateTest { session = WcSession( wallet = MockUserWalletFactory.create(), networks = setOf(), - account = null, + account = Account.CryptoPortfolio.createMainAccount(MockUserWalletFactory.create().walletId), securityStatus = CheckDAppResult.FAILED_TO_VERIFY, connectingTime = 0L, sdkModel = WcSdkSession( diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSession.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSession.kt index cf3f4c9f37..20ffd7cea6 100644 --- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSession.kt +++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSession.kt @@ -8,7 +8,7 @@ import com.tangem.domain.models.wallet.UserWallet data class WcSession( val wallet: UserWallet, - val account: Account.CryptoPortfolio?, + val account: Account.CryptoPortfolio, val networks: Set, val sdkModel: WcSdkSession, val securityStatus: CheckDAppResult, diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionApprove.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionApprove.kt index e55e69f940..75c6fb808c 100644 --- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionApprove.kt +++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionApprove.kt @@ -6,6 +6,6 @@ import com.tangem.domain.models.wallet.UserWallet data class WcSessionApprove( val wallet: UserWallet, - val account: Account?, + val account: Account, val network: List, ) \ No newline at end of file diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionDTO.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionDTO.kt index eaee191c92..21a22308f8 100644 --- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionDTO.kt +++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionDTO.kt @@ -9,7 +9,7 @@ import com.tangem.domain.models.wallet.UserWalletId data class WcSessionDTO( val topic: String, val walletId: UserWalletId, - val accountId: AccountId? = null, + val accountId: AccountId = AccountId.forMainCryptoPortfolio(walletId), val url: String?, val securityStatus: CheckDAppResult = CheckDAppResult.FAILED_TO_VERIFY, val connectingTime: Long? = null, diff --git a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionProposal.kt b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionProposal.kt index dbec25e6d2..9850e0418e 100644 --- a/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionProposal.kt +++ b/domain/wallet-connect/models/src/main/java/com/tangem/domain/walletconnect/model/WcSessionProposal.kt @@ -9,8 +9,7 @@ import com.tangem.domain.walletconnect.model.sdkcopy.WcAppMetaData data class WcSessionProposal( val dAppMetaData: WcAppMetaData, - val proposalNetwork: Map, - val proposalAccountNetwork: Map?, + val proposalAccountNetwork: Map, val securityStatus: CheckDAppResult, ) { diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcPairComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcPairComponent.kt index 220f294b49..1675ff7fba 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcPairComponent.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcPairComponent.kt @@ -66,7 +66,6 @@ internal class WcPairComponent( else -> model.stackNavigation.pop() } is WcAppInfoRoutes.SelectNetworks, - is WcAppInfoRoutes.SelectWallet, is WcAppInfoRoutes.PortfolioSelector, -> model.stackNavigation.pop() } @@ -102,14 +101,6 @@ internal class WcPairComponent( callback = model, ), ) - is WcAppInfoRoutes.SelectWallet -> WcSelectWalletComponent( - appComponentContext = appComponentContext, - params = WcSelectWalletComponent.WcSelectWalletParams( - selectedWalletId = config.selectedWalletId, - onDismiss = ::dismiss, - callback = model, - ), - ) WcAppInfoRoutes.PortfolioSelector -> portfolioSelectorComponentFactory.create( context = appComponentContext, params = PortfolioSelectorComponent.Params( diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcSelectWalletComponent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcSelectWalletComponent.kt deleted file mode 100644 index 93e8566ec0..0000000000 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/components/WcSelectWalletComponent.kt +++ /dev/null @@ -1,216 +0,0 @@ -package com.tangem.features.walletconnect.connections.components - -import android.content.res.Configuration -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.key -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.tooling.preview.Devices -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.util.fastForEach -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.tangem.common.ui.userwallet.UserWalletItem -import com.tangem.common.ui.userwallet.state.UserWalletItemUM -import com.tangem.core.decompose.context.AppComponentContext -import com.tangem.core.decompose.model.getOrCreateModel -import com.tangem.core.ui.components.block.TangemBlockCardColors -import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig -import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent -import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet -import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle -import com.tangem.core.ui.decompose.ComposableBottomSheetComponent -import com.tangem.core.ui.extensions.TextReference -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.stringReference -import com.tangem.core.ui.extensions.wrappedList -import com.tangem.core.ui.res.TangemTheme -import com.tangem.core.ui.res.TangemThemePreview -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.features.walletconnect.connections.model.WcSelectWalletModel -import com.tangem.features.walletconnect.impl.R -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf - -internal class WcSelectWalletComponent( - appComponentContext: AppComponentContext, - private val params: WcSelectWalletParams, -) : AppComponentContext by appComponentContext, ComposableBottomSheetComponent { - - private val model: WcSelectWalletModel = getOrCreateModel(params = params) - - override fun dismiss() { - params.onDismiss() - } - - @Composable - override fun BottomSheet() { - val state by model.state.collectAsStateWithLifecycle() - WcSelectWalletModalBS( - wallets = state.wallets, - selectedWalletId = state.selectedUserWalletId, - onBack = router::pop, - onDismiss = ::dismiss, - ) - } - - interface ModelCallback { - fun onWalletSelected(userWalletId: UserWalletId) - } - - data class WcSelectWalletParams( - val selectedWalletId: UserWalletId, - val callback: ModelCallback, - val onDismiss: () -> Unit, - ) -} - -@Composable -private fun WcSelectWalletModalBS( - wallets: ImmutableList, - selectedWalletId: UserWalletId, - onBack: () -> Unit, - onDismiss: () -> Unit, - modifier: Modifier = Modifier, -) { - if (wallets.isEmpty()) return - - TangemModalBottomSheet( - config = TangemBottomSheetConfig( - isShown = true, - onDismissRequest = onDismiss, - content = TangemBottomSheetConfigContent.Empty, - ), - onBack = onBack, - containerColor = TangemTheme.colors.background.primary, - title = { - TangemModalBottomSheetTitle( - title = resourceReference(R.string.common_choose_wallet), - startIconRes = R.drawable.ic_back_24, - onStartClick = onBack, - ) - }, - content = { - WcSelectWalletContent( - modifier = modifier.padding(start = 16.dp, end = 16.dp, bottom = 16.dp), - wallets = wallets, - selectedWalletId = selectedWalletId, - ) - }, - ) -} - -@Composable -private fun WcSelectWalletContent( - wallets: ImmutableList, - selectedWalletId: UserWalletId, - modifier: Modifier = Modifier, -) { - Column(modifier = modifier) { - wallets.fastForEach { state -> - key(state.id) { - val baseModifier = Modifier - .clip(RoundedCornerShape(14.dp)) - .clickable(onClick = state.onClick) - val itemModifier = if (state.id == selectedWalletId.stringValue) { - baseModifier.border( - width = 1.dp, - color = TangemTheme.colors.text.accent, - shape = RoundedCornerShape(14.dp), - ) - } else { - baseModifier - } - UserWalletItem( - modifier = itemModifier, - state = state, - blockColors = TangemBlockCardColors.copy( - containerColor = Color.Unspecified, - disabledContainerColor = Color.Unspecified, - ), - ) - } - } - } -} - -@Suppress("LongMethod") -@Composable -@Preview(showBackground = true, device = Devices.PIXEL_7_PRO) -@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES) -private fun WcSelectWalletContent_Preview() { - val wallets = persistentListOf( - UserWalletItemUM( - id = "user_wallet_1", - name = stringReference("Tangem 2.0"), - information = getInformation(42), - balance = UserWalletItemUM.Balance.Loaded("1 496,34 $", isFlickering = false), - isEnabled = true, - onClick = {}, - ), - UserWalletItemUM( - id = "user_wallet_2", - name = stringReference("Tangem White"), - information = getInformation(24), - balance = UserWalletItemUM.Balance.Loaded("1 496,34 $", isFlickering = false), - isEnabled = true, - onClick = {}, - ), - UserWalletItemUM( - id = "user_wallet_3", - name = stringReference("Bitcoin"), - information = getInformation(1), - balance = UserWalletItemUM.Balance.Loaded("1 496,34 $", isFlickering = false), - isEnabled = true, - onClick = {}, - ), - UserWalletItemUM( - id = "user_wallet_4", - name = stringReference("Tangem 1.0"), - information = getInformation(21), - balance = UserWalletItemUM.Balance.Loaded("1 496,34 $", isFlickering = false), - isEnabled = true, - onClick = {}, - ), - UserWalletItemUM( - id = "user_wallet_4", - name = stringReference("Tangem 1.0"), - information = UserWalletItemUM.Information.Loading, - balance = UserWalletItemUM.Balance.Loaded("1 496,34 $", isFlickering = false), - isEnabled = true, - onClick = {}, - ), - UserWalletItemUM( - id = "user_wallet_4", - name = stringReference("Tangem 1.0"), - information = UserWalletItemUM.Information.Failed, - balance = UserWalletItemUM.Balance.Loaded("1 496,34 $", isFlickering = false), - isEnabled = true, - onClick = {}, - ), - ) - TangemThemePreview { - WcSelectWalletModalBS( - wallets = wallets, - selectedWalletId = UserWalletId(wallets.first().id.encodeToByteArray()), - onBack = {}, - onDismiss = {}, - ) - } -} - -private fun getInformation(tokenCount: Int): UserWalletItemUM.Information.Loaded { - val text = TextReference.PluralRes( - id = R.plurals.card_label_token_count, - count = tokenCount, - formatArgs = wrappedList(tokenCount), - ) - return UserWalletItemUM.Information.Loaded(text) -} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcAppInfoUM.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcAppInfoUM.kt index cf9d41811a..16a0bfeda6 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcAppInfoUM.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcAppInfoUM.kt @@ -27,9 +27,7 @@ internal sealed class WcAppInfoUM : TangemBottomSheetConfigContent { val verifiedDAppState: VerifiedDAppState, val appSubtitle: String, val notification: WcAppInfoSecurityNotification?, - val portfolioSelectRow: PortfolioSelectUM?, - val walletName: String, - val onWalletClick: (() -> Unit)?, + val portfolioSelectRow: PortfolioSelectUM, val networksInfo: WcNetworksInfo, val onNetworksClick: () -> Unit, override val connectButtonConfig: WcPrimaryButtonConfig, diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt index d59a81f60d..a8bc0da03c 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt @@ -21,16 +21,11 @@ import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.message.SnackbarMessage import com.tangem.core.ui.message.ToastMessage -import com.tangem.domain.account.producer.SingleAccountListProducer -import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.models.account.Account import com.tangem.domain.models.account.AccountStatus import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.models.wallet.isLocked -import com.tangem.domain.models.wallet.isMultiCurrency import com.tangem.domain.walletconnect.WcAnalyticEvents import com.tangem.domain.walletconnect.model.WcPairError import com.tangem.domain.walletconnect.model.WcPairError.Unknown @@ -40,16 +35,17 @@ import com.tangem.domain.walletconnect.model.WcSessionProposal import com.tangem.domain.walletconnect.model.sdkcopy.WcAppMetaData import com.tangem.domain.walletconnect.usecase.pair.WcPairState import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase -import com.tangem.domain.wallets.usecase.GetWalletsUseCase import com.tangem.features.account.PortfolioFetcher import com.tangem.features.account.PortfolioSelectorComponent import com.tangem.features.account.PortfolioSelectorController import com.tangem.features.walletconnect.connections.components.WcPairComponent import com.tangem.features.walletconnect.connections.components.WcSelectNetworksComponent -import com.tangem.features.walletconnect.connections.components.WcSelectWalletComponent import com.tangem.features.walletconnect.connections.entity.WcAppInfoUM import com.tangem.features.walletconnect.connections.entity.WcPrimaryButtonConfig -import com.tangem.features.walletconnect.connections.model.transformers.* +import com.tangem.features.walletconnect.connections.model.transformers.WcAppInfoTransformer +import com.tangem.features.walletconnect.connections.model.transformers.WcConnectButtonProgressTransformer +import com.tangem.features.walletconnect.connections.model.transformers.WcDAppVerifiedStateConverter +import com.tangem.features.walletconnect.connections.model.transformers.WcNetworksSelectedTransformer import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes import com.tangem.features.walletconnect.impl.R import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -61,11 +57,8 @@ import kotlin.properties.Delegates import com.tangem.utils.transformer.update as transformerUpdate internal interface WcPairComponentCallback : - WcSelectWalletComponent.ModelCallback, WcSelectNetworksComponent.ModelCallback -private const val WC_WALLETS_SELECTOR_MIN_COUNT = 2 - @Stable @ModelScoped @Suppress("LongParameterList", "LargeClass") @@ -75,11 +68,9 @@ internal class WcPairModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val analytics: AnalyticsEventHandler, val selectorController: PortfolioSelectorController, - private val singleAccountListSupplier: SingleAccountListSupplier, private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase, portfolioFetcherFactory: PortfolioFetcher.Factory, wcPairUseCaseFactory: WcPairUseCase.Factory, - getWalletsUseCase: GetWalletsUseCase, paramsContainer: ParamsContainer, ) : Model(), WcPairComponentCallback { @@ -102,9 +93,6 @@ internal class WcPairModel @Inject constructor( override val onBack: () -> Unit = { stackNavigation.pop() } } - private val selectedUserWalletFlow: MutableStateFlow by lazy { - MutableStateFlow(getWalletsUseCase.invokeSync().first { it.walletId == params.userWalletId }) - } private val selectedPortfolio = MutableSharedFlow>( replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST, @@ -119,14 +107,15 @@ internal class WcPairModel @Inject constructor( init { modelScope.launch { - val params = SingleAccountListProducer.Params(params.userWalletId) - val accountList = singleAccountListSupplier.getSyncOrNull(params) - if (accountList == null) { + val portfolioBalance = portfolioFetcher.data.first().balances + .firstNotNullOfOrNull { (walletId, balance) -> + if (params.userWalletId == walletId) balance else null + } + if (portfolioBalance == null) { router.pop() return@launch } - val firstAccount = accountList.accounts.first() - selectorController.selectAccount(firstAccount.accountId) + selectorController.selectAccount(portfolioBalance.accountsBalance.mainAccount.accountId) combineFlows(portfolioFetcher) } } @@ -135,10 +124,12 @@ internal class WcPairModel @Inject constructor( combine( flow = portfolioFetcher.data, flow2 = selectorController.selectedAccountWithData(portfolioFetcher) - .distinctUntilChanged() .filterNotNull() .onEach { selectedPortfolio.tryEmit(it) } - .onEach { stackNavigation.pop() }, + .runningReduce { _, new -> + stackNavigation.pop() + new + }, flow3 = wcPairUseCase(), flow4 = isAccountsModeEnabledUseCase(), transform = { portfolios, selected, pairState, isAccountMode -> @@ -155,9 +146,9 @@ internal class WcPairModel @Inject constructor( private suspend fun handlePairState( pairState: WcPairState, - portfolios: PortfolioFetcher.Data? = null, - selected: Pair? = null, - isAccountMode: Boolean? = null, + portfolios: PortfolioFetcher.Data, + selected: Pair, + isAccountMode: Boolean, ) { when (pairState) { is WcPairState.Approving.Loading -> appInfoUiState.transformerUpdate( @@ -184,36 +175,32 @@ internal class WcPairModel @Inject constructor( pairState = pairState, portfolios = portfolios, selected = selected, + isAccountMode = isAccountMode, ) } } private suspend fun handleProposalState( pairState: WcPairState.Proposal, - portfolios: PortfolioFetcher.Data? = null, - selected: Pair? = null, + portfolios: PortfolioFetcher.Data, + selected: Pair, + isAccountMode: Boolean, ) { - val availableWallets = pairState.dAppSession.proposalNetwork.keys - .filter { !it.isLocked && it.isMultiCurrency } sessionProposal = pairState.dAppSession - val selectedUserWalletFlow = this.selectedUserWalletFlow - val portfolioWallet = selected?.first - val portfolioAccount = selected?.second - val portfolioAccountId = portfolioAccount?.account?.accountId + val portfolioAccount = selected.second + val portfolioAccountId = portfolioAccount.account.accountId val proposalAccountNetwork = sessionProposal.proposalAccountNetwork - val foundNetwork = if (portfolioAccountId != null) { - requireNotNull(proposalAccountNetwork)[portfolioAccountId] - } else { - sessionProposal.proposalNetwork[selectedUserWalletFlow.value] - } + val foundNetwork = proposalAccountNetwork[portfolioAccountId] if (foundNetwork == null) { processError(Unknown("Selected wallet not found")) } else { - val portfolioSelectRow = tryToCreatePortfolioSelectRow(selected, portfolios) - if (proposalAccountNetwork != null) { - selectorController.isEnabled.value = { _, account -> - proposalAccountNetwork.contains(account.account.accountId) - } + val portfolioSelectRow = createPortfolioSelectRow( + selectedPortfolio = selected, + portfolios = portfolios, + isAccountMode = isAccountMode, + ) + selectorController.isEnabled.value = { _, account -> + proposalAccountNetwork.contains(account.account.accountId) } proposalNetwork = foundNetwork additionallyEnabledNetworks = proposalNetwork.available @@ -224,13 +211,6 @@ internal class WcPairModel @Inject constructor( onDismiss = ::rejectPairing, onConnect = ::onConnect, portfolioSelectRow = portfolioSelectRow, - onWalletClick = { - stackNavigation.pushNew( - WcAppInfoRoutes.SelectWallet(selectedUserWalletFlow.value.walletId), - ) - }.takeIf { - portfolioSelectRow == null && availableWallets.size >= WC_WALLETS_SELECTOR_MIN_COUNT - }, onNetworksClick = { stackNavigation.pushNew( WcAppInfoRoutes.SelectNetworks( @@ -242,7 +222,6 @@ internal class WcPairModel @Inject constructor( ), ) }, - userWallet = portfolioWallet ?: selectedUserWalletFlow.value, proposalNetwork = proposalNetwork, additionallyEnabledNetworks = additionallyEnabledNetworks, ), @@ -250,17 +229,15 @@ internal class WcPairModel @Inject constructor( } } - private suspend fun tryToCreatePortfolioSelectRow( - selectedPortfolio: Pair?, - portfolios: PortfolioFetcher.Data?, - ): PortfolioSelectUM? { - selectedPortfolio ?: return null - portfolios ?: return null + private suspend fun createPortfolioSelectRow( + selectedPortfolio: Pair, + portfolios: PortfolioFetcher.Data, + isAccountMode: Boolean, + ): PortfolioSelectUM { val (wallet, portfolioAccount) = selectedPortfolio val account = when (val account = portfolioAccount.account) { is Account.CryptoPortfolio -> account } - val isAccountMode = selectorController.isAccountMode.first() val icon: AccountIconUM.CryptoPortfolio? val name: TextReference if (isAccountMode) { @@ -303,15 +280,16 @@ internal class WcPairModel @Inject constructor( private fun connect() { val enabledAvailableNetworks = proposalNetwork.available.filter { network -> network in additionallyEnabledNetworks } - val selectedPortfolio = selectedPortfolio.replayCache.firstOrNull() - val wallet = selectedPortfolio?.first ?: selectedUserWalletFlow.value - val account = selectedPortfolio?.second?.account + val selectedPortfolio = selectedPortfolio.replayCache + .firstOrNull() + ?: return + val (wallet, account) = selectedPortfolio modelScope.launch { analytics.send( WcAnalyticEvents.PairButtonConnect( dAppName = sessionProposal.dAppMetaData.name, - accountDerivation = account?.derivationIndex?.value, + accountDerivation = account.account.derivationIndex.value, ), ) } @@ -319,7 +297,7 @@ internal class WcPairModel @Inject constructor( WcSessionApprove( wallet = wallet, network = enabledAvailableNetworks + proposalNetwork.required, - account = account, + account = account.account, ), ) } @@ -375,20 +353,6 @@ internal class WcPairModel @Inject constructor( alert?.let { stackNavigation.pushNew(it) } } - override fun onWalletSelected(userWalletId: UserWalletId) { - val selectedUserWallet = sessionProposal.proposalNetwork.keys.first { it.walletId == userWalletId } - proposalNetwork = sessionProposal.proposalNetwork[selectedUserWallet] ?: return - selectedUserWalletFlow.update { selectedUserWallet } - additionallyEnabledNetworks = proposalNetwork.available - appInfoUiState.transformerUpdate( - WcAppInfoWalletChangedTransformer( - selectedUserWallet = selectedUserWallet, - proposalNetwork = proposalNetwork, - additionallyEnabledNetworks = additionallyEnabledNetworks, - ), - ) - } - override fun onNetworksSelected(selectedNetworks: Set) { additionallyEnabledNetworks = selectedNetworks appInfoUiState.transformerUpdate( diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcSelectWalletModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcSelectWalletModel.kt deleted file mode 100644 index 04132e0692..0000000000 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcSelectWalletModel.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.tangem.features.walletconnect.connections.model - -import androidx.compose.runtime.Stable -import com.tangem.core.decompose.di.ModelScoped -import com.tangem.core.decompose.model.Model -import com.tangem.core.decompose.model.ParamsContainer -import com.tangem.core.decompose.navigation.Router -import com.tangem.core.decompose.ui.UiMessageSender -import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.features.wallet.utils.UserWalletsFetcher -import com.tangem.features.walletconnect.connections.components.WcSelectWalletComponent.WcSelectWalletParams -import com.tangem.features.walletconnect.connections.entity.WcAppInfoWalletUM -import com.tangem.features.walletconnect.connections.utils.WcUserWalletsFetcher -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.collections.immutable.persistentListOf -import kotlinx.coroutines.flow.* -import javax.inject.Inject - -@Suppress("LongParameterList") -@Stable -@ModelScoped -internal class WcSelectWalletModel @Inject constructor( - paramsContainer: ParamsContainer, - messageSender: UiMessageSender, - userWalletsFetcherFactory: UserWalletsFetcher.Factory, - private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, - private val router: Router, - override val dispatchers: CoroutineDispatcherProvider, -) : Model() { - - private val params = paramsContainer.require() - - internal val state: StateFlow - field = MutableStateFlow( - WcAppInfoWalletUM( - wallets = persistentListOf(), - selectedUserWalletId = params.selectedWalletId, - ), - ) - - private val userWalletsFetcher = WcUserWalletsFetcher( - userWalletsFetcherFactory = userWalletsFetcherFactory, - singleAccountStatusListSupplier = singleAccountStatusListSupplier, - messageSender = messageSender, - onWalletSelected = ::onWalletSelected, - ) - - init { - userWalletsFetcher - .userWallets - .onEach { state.update { state -> state.copy(wallets = it) } } - .launchIn(modelScope) - } - - private fun onWalletSelected(userWalletId: UserWalletId) { - params.callback.onWalletSelected(userWalletId) - router.pop() - } -} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoTransformer.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoTransformer.kt index d6099eaaa2..e8597c20e5 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoTransformer.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoTransformer.kt @@ -3,7 +3,6 @@ package com.tangem.features.walletconnect.connections.model.transformers import com.domain.blockaid.models.dapp.CheckDAppResult import com.tangem.common.ui.account.PortfolioSelectUM import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.walletconnect.model.WcSessionProposal import com.tangem.features.walletconnect.connections.entity.WcAppInfoSecurityNotification import com.tangem.features.walletconnect.connections.entity.WcAppInfoUM @@ -16,10 +15,8 @@ internal class WcAppInfoTransformer( private val dAppVerifiedStateConverter: WcDAppVerifiedStateConverter, private val onDismiss: () -> Unit, private val onConnect: (securityStatus: CheckDAppResult) -> Unit, - private val portfolioSelectRow: PortfolioSelectUM?, - private val onWalletClick: (() -> Unit)?, + private val portfolioSelectRow: PortfolioSelectUM, private val onNetworksClick: () -> Unit, - private val userWallet: UserWallet, private val proposalNetwork: WcSessionProposal.ProposalNetwork, private val additionallyEnabledNetworks: Set, ) : Transformer { @@ -33,8 +30,6 @@ internal class WcAppInfoTransformer( ), appSubtitle = WcAppSubtitleConverter.convert(dAppSession.dAppMetaData), notification = createNotification(dAppSession.securityStatus), - walletName = userWallet.name, - onWalletClick = onWalletClick, portfolioSelectRow = portfolioSelectRow, networksInfo = WcNetworksInfoConverter.convert( value = WcNetworksInfoConverter.Input( diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoWalletChangedTransformer.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoWalletChangedTransformer.kt deleted file mode 100644 index 54d753bd72..0000000000 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcAppInfoWalletChangedTransformer.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.tangem.features.walletconnect.connections.model.transformers - -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.walletconnect.model.WcSessionProposal -import com.tangem.features.walletconnect.connections.entity.WcAppInfoUM -import com.tangem.utils.transformer.Transformer - -internal class WcAppInfoWalletChangedTransformer( - private val selectedUserWallet: UserWallet, - private val proposalNetwork: WcSessionProposal.ProposalNetwork, - private val additionallyEnabledNetworks: Set, -) : Transformer { - override fun transform(prevState: WcAppInfoUM): WcAppInfoUM { - val contentState = prevState as? WcAppInfoUM.Content ?: return prevState - return contentState.copy( - walletName = selectedUserWallet.name, - networksInfo = WcNetworksInfoConverter.convert( - WcNetworksInfoConverter.Input( - missingNetworks = proposalNetwork.missingRequired, - requiredNetworks = proposalNetwork.required, - availableNetworks = proposalNetwork.available, - notAddedNetworks = proposalNetwork.notAdded, - additionallyEnabledNetworks = additionallyEnabledNetworks, - ), - ), - connectButtonConfig = prevState.connectButtonConfig.copy( - enabled = WcConnectButtonAvailabilityConverter.convert( - WcConnectButtonAvailabilityConverter.Input( - missingNetworks = proposalNetwork.missingRequired, - requiredNetworks = proposalNetwork.required, - availableNetworks = proposalNetwork.available, - selectedNetworks = additionallyEnabledNetworks, - ), - ), - ), - ) - } -} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcSessionsAccountModeTransformer.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcSessionsAccountModeTransformer.kt index f3991ee130..7ff2f97a29 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcSessionsAccountModeTransformer.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcSessionsAccountModeTransformer.kt @@ -49,7 +49,7 @@ internal class WcSessionsAccountModeTransformer( items.add(walletHeader) accountList.accounts.filterIsInstance().forEach accountsForEach@{ account -> - val accountSessions = sessions.filter { it.account?.accountId == account.accountId } + val accountSessions = sessions.filter { it.account.accountId == account.accountId } if (accountSessions.isEmpty()) return@accountsForEach val connectedApps = accountSessions.map { dappSession -> with(dappSession.sdkModel) { diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routes/WcAppInfoRoutes.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routes/WcAppInfoRoutes.kt index e2a866155b..63edee72e6 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routes/WcAppInfoRoutes.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/routes/WcAppInfoRoutes.kt @@ -3,7 +3,6 @@ package com.tangem.features.walletconnect.connections.routes import androidx.compose.runtime.Immutable import com.tangem.core.decompose.navigation.Route import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWalletId import kotlinx.serialization.Serializable @Serializable @@ -15,9 +14,6 @@ internal sealed class WcAppInfoRoutes : Route { @Serializable data object PortfolioSelector : WcAppInfoRoutes() - @Serializable - data class SelectWallet(val selectedWalletId: UserWalletId) : WcAppInfoRoutes() - @Serializable data class SelectNetworks( val missingRequiredNetworks: Set, diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoBS.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoBS.kt index 9bfbb0ec01..ad8dad09c5 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoBS.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcAppInfoBS.kt @@ -22,8 +22,6 @@ import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter @@ -273,19 +271,7 @@ private fun WcAppInfoSecondBlock(state: WcAppInfoUM.Content, modifier: Modifier val itemsModifier = Modifier .fillMaxWidth() .padding(TangemTheme.dimens.spacing12) - if (state.portfolioSelectRow != null) { - PortfolioRowItem(portfolioSelectRow = state.portfolioSelectRow) - } else { - WalletRowItem( - modifier = if (state.onWalletClick != null) { - Modifier.clickableSingle(onClick = state.onWalletClick) - } else { - Modifier - }.then(itemsModifier), - walletName = state.walletName, - showEndIcon = state.onWalletClick != null, - ) - } + PortfolioRowItem(portfolioSelectRow = state.portfolioSelectRow) HorizontalDivider(thickness = 1.dp, color = TangemTheme.colors.stroke.primary) SelectNetworksBlock( modifier = Modifier @@ -341,56 +327,6 @@ private fun PortfolioRowItem(portfolioSelectRow: PortfolioSelectUM, modifier: Mo } } -@Composable -private fun WalletRowItem(walletName: String, showEndIcon: Boolean, modifier: Modifier = Modifier) { - Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) { - Icon( - modifier = Modifier - .size(24.dp) - .testTag(WalletConnectBottomSheetTestTags.WALLET_ICON), - painter = painterResource(R.drawable.ic_wallet_new_24), - contentDescription = null, - tint = TangemTheme.colors.icon.accent, - ) - Row( - modifier = Modifier.weight(1f), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - modifier = Modifier - .padding(start = TangemTheme.dimens.spacing4) - .testTag(WalletConnectBottomSheetTestTags.WALLET_NAME_TITLE), - text = stringResourceSafe(R.string.manage_tokens_network_selector_wallet), - style = TangemTheme.typography.body1, - color = TangemTheme.colors.text.primary1, - maxLines = 1, - ) - Text( - modifier = Modifier - .padding(start = TangemTheme.dimens.spacing16) - .testTag(WalletConnectBottomSheetTestTags.WALLET_NAME), - text = walletName, - textAlign = TextAlign.End, - style = TangemTheme.typography.body1, - color = TangemTheme.colors.text.tertiary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } - if (showEndIcon) { - Icon( - modifier = Modifier - .padding(start = TangemTheme.dimens.spacing12) - .size(width = 18.dp, height = 24.dp), - painter = painterResource(R.drawable.ic_select_18_24), - contentDescription = null, - tint = TangemTheme.colors.icon.informative, - ) - } - } -} - @Composable private fun SelectNetworksBlock(networksInfo: WcNetworksInfo, modifier: Modifier = Modifier) { Row( @@ -673,9 +609,7 @@ private class WcAppInfoStateProvider : CollectionPreviewParameterProvider Unit, -) { - - private val userWalletsFetcher = userWalletsFetcherFactory.create( - messageSender = messageSender, - onlyMultiCurrency = true, - isAuthMode = false, - isClickableIfLocked = false, - onWalletClick = { onWalletSelected(it) }, - ) - - @OptIn(ExperimentalCoroutinesApi::class) - val userWallets: Flow> = userWalletsFetcher.userWallets - .flatMapLatest { listOfWalletItem -> - val flows = listOfWalletItem.map(::getTokenListFlow) - combine(flows) { it.toList().toImmutableList() } - } - - private fun getTokenListFlow(walletItem: UserWalletItemUM): Flow { - return singleAccountStatusListSupplier(userWalletId = UserWalletId(walletItem.id)).map { accountStatusList -> - val information = when (accountStatusList.totalFiatBalance) { - is TotalFiatBalance.Failed -> UserWalletItemUM.Information.Failed - is TotalFiatBalance.Loading -> UserWalletItemUM.Information.Loading - is TotalFiatBalance.Loaded -> tokenCountInfo(accountStatusList.flattenCurrencies().size) - } - - walletItem.copy(information = information) - } - } - - private fun tokenCountInfo(count: Int): UserWalletItemUM.Information.Loaded { - val text = TextReference.PluralRes( - id = R.plurals.card_label_token_count, - count = count, - formatArgs = wrappedList(count), - ) - return UserWalletItemUM.Information.Loaded(text) - } -} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/di/WalletConnectModelModule.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/di/WalletConnectModelModule.kt index f40742eb25..620599339d 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/di/WalletConnectModelModule.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/di/WalletConnectModelModule.kt @@ -28,11 +28,6 @@ internal interface WalletConnectModelModule { @ClassKey(WcPairModel::class) fun bindWcPairModel(model: WcPairModel): Model - @Binds - @IntoMap - @ClassKey(WcSelectWalletModel::class) - fun bindWcSelectWalletModel(model: WcSelectWalletModel): Model - @Binds @IntoMap @ClassKey(WcSelectNetworksModel::class) diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt index 11fba2839f..78f0d51df5 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt @@ -137,7 +137,7 @@ internal class WcAddNetworkModel @Inject constructor( network = useCase.network, emulationStatus = null, securityStatus = CheckDAppResult.FAILED_TO_VERIFY, - accountDerivation = useCase.session.account?.derivationIndex?.value, + accountDerivation = useCase.session.account.derivationIndex.value, ), ) diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt index a156c5a69c..493b5158d4 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt @@ -426,7 +426,7 @@ internal class WcSendTransactionModel @Inject constructor( rawRequest = useCase.rawSdkRequest, network = useCase.network, securityStatus = securityStatusState.value.toCheckDAppResult(), - accountDerivation = useCase.session.account?.derivationIndex?.value, + accountDerivation = useCase.session.account.derivationIndex.value, ) analytics.send(event) showSuccessSignMessage() @@ -466,7 +466,7 @@ internal class WcSendTransactionModel @Inject constructor( network = useCase.network, emulationStatus = emulationStatus, securityStatus = securityCheck.toCheckDAppResult(), - accountDerivation = useCase.session.account?.derivationIndex?.value, + accountDerivation = useCase.session.account.derivationIndex.value, ), ) diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt index 7a0a21fe7f..2f36707a60 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt @@ -143,7 +143,7 @@ internal class WcSignTransactionModel @Inject constructor( rawRequest = useCase.rawSdkRequest, network = useCase.network, securityStatus = CheckDAppResult.FAILED_TO_VERIFY, - accountDerivation = useCase.session.account?.derivationIndex?.value, + accountDerivation = useCase.session.account.derivationIndex.value, ) analytics.send(event) showSuccessSignMessage() @@ -172,7 +172,7 @@ internal class WcSignTransactionModel @Inject constructor( network = useCase.network, emulationStatus = null, securityStatus = CheckDAppResult.FAILED_TO_VERIFY, - accountDerivation = useCase.session.account?.derivationIndex?.value, + accountDerivation = useCase.session.account.derivationIndex.value, ), )