Updated on 2026-08-14
This commit is contained in:
parent
a04992591a
commit
d3320b9e8b
14 changed files with 370 additions and 111 deletions
|
|
@ -4,6 +4,7 @@ import android.content.res.Configuration
|
|||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Icon
|
||||
|
|
@ -30,13 +31,18 @@ import com.tangem.core.ui.res.TangemThemePreview
|
|||
import com.tangem.domain.models.account.AccountName
|
||||
|
||||
@Composable
|
||||
fun PortfolioSelectRow(state: PortfolioSelectUM, modifier: Modifier = Modifier) {
|
||||
fun PortfolioSelectRow(
|
||||
state: PortfolioSelectUM,
|
||||
modifier: Modifier = Modifier,
|
||||
leftContent: @Composable RowScope.() -> Unit = {},
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.clickable(enabled = state.isMultiChoice, onClick = state.onClick)
|
||||
.padding(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
leftContent()
|
||||
val leftText = if (state.isAccountMode) R.string.account_details_title else R.string.wc_common_wallet
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
|
|
@ -97,6 +103,11 @@ private fun PortfolioSelectRowPreview(@PreviewParameter(PreviewProvider::class)
|
|||
|
||||
private class PreviewProvider : PreviewParameterProvider<PortfolioSelectUM> {
|
||||
|
||||
override val values: Sequence<PortfolioSelectUM>
|
||||
get() = sequenceOf(PortfolioSelectRowPreviewData.account, PortfolioSelectRowPreviewData.wallet)
|
||||
}
|
||||
|
||||
object PortfolioSelectRowPreviewData {
|
||||
val account
|
||||
get() = PortfolioSelectUM(
|
||||
icon = AccountIconPreviewData.randomAccountIcon(),
|
||||
|
|
@ -113,7 +124,4 @@ private class PreviewProvider : PreviewParameterProvider<PortfolioSelectUM> {
|
|||
isAccountMode = false,
|
||||
onClick = {},
|
||||
)
|
||||
|
||||
override val values: Sequence<PortfolioSelectUM>
|
||||
get() = sequenceOf(account, wallet)
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ class GetTokenMarketCryptoCurrency(
|
|||
userWalletId: UserWalletId,
|
||||
tokenMarketParams: TokenMarketParams,
|
||||
network: TokenMarketInfo.Network,
|
||||
accountIndex: DerivationIndex? = null,
|
||||
accountIndex: DerivationIndex,
|
||||
): CryptoCurrency? {
|
||||
return marketsTokenRepository.createCryptoCurrency(
|
||||
userWalletId = userWalletId,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.domain.markets.FilterAvailableNetworksForWalletUseCase
|
|||
import com.tangem.domain.markets.GetTokenMarketCryptoCurrency
|
||||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.domain.markets.TokenMarketParams
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
|
|
@ -29,7 +30,8 @@ internal class AvailableToAddDataConverter @Inject constructor(
|
|||
): AvailableToAddData {
|
||||
suspend fun AccountStatus.getAvailableToAddAccount(wallet: UserWallet): AvailableToAddAccount {
|
||||
val addedNetworks = availableNetworks
|
||||
.mapNotNull { createCryptoCurrency(wallet, it, marketParams) }
|
||||
.mapNotNull { createCryptoCurrency(wallet, it, marketParams, this.account) }
|
||||
// todo account poor performance, investigate, e.g 20 accounts and USDC token for adding
|
||||
.mapNotNull { getAccountCurrencyStatusUseCase.invokeSync(wallet.walletId, it) }
|
||||
.mapNotNull { it.getOrNull()?.status?.currency?.network }
|
||||
.toSet()
|
||||
|
|
@ -82,9 +84,16 @@ internal class AvailableToAddDataConverter @Inject constructor(
|
|||
userWallet: UserWallet,
|
||||
network: TokenMarketInfo.Network,
|
||||
marketParams: TokenMarketParams,
|
||||
): CryptoCurrency? = getTokenMarketCryptoCurrency(
|
||||
userWalletId = userWallet.walletId,
|
||||
tokenMarketParams = marketParams,
|
||||
network = network,
|
||||
)
|
||||
account: Account,
|
||||
): CryptoCurrency? {
|
||||
val derivationIndex = when (account) {
|
||||
is Account.CryptoPortfolio -> account.derivationIndex
|
||||
}
|
||||
return getTokenMarketCryptoCurrency(
|
||||
userWalletId = userWallet.walletId,
|
||||
tokenMarketParams = marketParams,
|
||||
network = network,
|
||||
accountIndex = derivationIndex,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -257,12 +257,17 @@ internal class AddToPortfolioModel @Inject constructor(
|
|||
userWallet: UserWallet,
|
||||
network: TokenMarketInfo.Network,
|
||||
account: AvailableToAddAccount,
|
||||
): CryptoCurrency? = getTokenMarketCryptoCurrency(
|
||||
userWalletId = userWallet.walletId,
|
||||
tokenMarketParams = addToPortfolioManager.token,
|
||||
network = network,
|
||||
accountIndex = (account.account as? AccountStatus.CryptoPortfolio)?.account?.derivationIndex,
|
||||
)
|
||||
): CryptoCurrency? {
|
||||
val accountIndex = when (account.account) {
|
||||
is AccountStatus.CryptoPortfolio -> account.account.account.derivationIndex
|
||||
}
|
||||
return getTokenMarketCryptoCurrency(
|
||||
userWalletId = userWallet.walletId,
|
||||
tokenMarketParams = addToPortfolioManager.token,
|
||||
network = network,
|
||||
accountIndex = accountIndex,
|
||||
)
|
||||
}
|
||||
|
||||
private fun routeToNetworkSelector(portfolio: SelectedPortfolio): AddToPortfolioRoutes.NetworkSelector {
|
||||
return AddToPortfolioRoutes.NetworkSelector(selectedPortfolio = portfolio)
|
||||
|
|
|
|||
|
|
@ -4,9 +4,14 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
|
|||
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.ui.UiMessageSender
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.message.ToastMessage
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.wallets.usecase.ColdWalletAndHasMissedDerivationsUseCase
|
||||
import com.tangem.features.markets.impl.R
|
||||
import com.tangem.features.markets.portfolio.add.api.SelectedNetwork
|
||||
import com.tangem.features.markets.portfolio.add.api.SelectedPortfolio
|
||||
import com.tangem.features.markets.portfolio.add.impl.AddTokenComponent
|
||||
|
|
@ -25,6 +30,7 @@ import javax.inject.Inject
|
|||
internal class AddTokenModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
private val uiBuilder: AddTokenUiBuilder,
|
||||
private val messageSender: UiMessageSender,
|
||||
private val coldWalletAndHasMissedDerivationsUseCase: ColdWalletAndHasMissedDerivationsUseCase,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
|
|
@ -70,13 +76,22 @@ internal class AddTokenModel @Inject constructor(
|
|||
val cryptoCurrency = selectedNetwork.cryptoCurrency
|
||||
val accountId = selectedPortfolio.account.account.account.accountId
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, add = cryptoCurrency)
|
||||
.onLeft {
|
||||
processError(error = it)
|
||||
uiState.value = um.toggleProgress(false)
|
||||
return@launch
|
||||
}
|
||||
|
||||
val status = getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = accountId.userWalletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
network = cryptoCurrency.network,
|
||||
).getOrNull() ?: return@launch
|
||||
params.callbacks.onTokenAdded(status.status)
|
||||
).getOrNull()
|
||||
if (status == null) {
|
||||
processError(error = null)
|
||||
} else {
|
||||
params.callbacks.onTokenAdded(status.status)
|
||||
}
|
||||
uiState.value = um.toggleProgress(false)
|
||||
}
|
||||
|
||||
|
|
@ -87,4 +102,10 @@ internal class AddTokenModel @Inject constructor(
|
|||
userWalletId = selectedPortfolio.userWallet.walletId,
|
||||
networksWithDerivationPath = mapOf(selectedNetwork.selectedNetwork.networkId to null),
|
||||
)
|
||||
|
||||
private fun processError(error: Throwable?) {
|
||||
val message = error?.message?.let { stringReference(it) }
|
||||
?: resourceReference(R.string.common_something_went_wrong)
|
||||
messageSender.send(ToastMessage(message = message))
|
||||
}
|
||||
}
|
||||
|
|
@ -87,19 +87,26 @@ internal class NewMarketsPortfolioDelegate @AssistedInject constructor(
|
|||
|
||||
private fun onAvailableNetworksFlow(): Flow<MyPortfolioUM> =
|
||||
portfolioWithThisCurrencyFLow().transformLatest { portfolioWithCurrency ->
|
||||
fun addFirstTokenUM() = MyPortfolioUM.AddFirstToken(
|
||||
onAddClick = onAddClick,
|
||||
addToPortfolioBSConfig = TangemBottomSheetConfig.Empty,
|
||||
)
|
||||
when (portfolioWithCurrency.flattenAddedCurrency.isEmpty()) {
|
||||
false -> emitAll(contentFlow(portfolioWithCurrency).distinctUntilChanged())
|
||||
true -> when (portfolioWithCurrency.hasMultiWallets) {
|
||||
true -> emit(addFirstTokenUM())
|
||||
true -> emitAll(addFirstTokenFlow())
|
||||
false -> emit(MyPortfolioUM.UnavailableForWallet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addFirstTokenFlow(): Flow<MyPortfolioUM> = buttonState.map {
|
||||
when (it) {
|
||||
AddButtonState.Loading -> MyPortfolioUM.Loading
|
||||
AddButtonState.Available -> MyPortfolioUM.AddFirstToken(
|
||||
onAddClick = onAddClick,
|
||||
addToPortfolioBSConfig = TangemBottomSheetConfig.Empty,
|
||||
)
|
||||
AddButtonState.Unavailable -> MyPortfolioUM.Unavailable
|
||||
}
|
||||
}
|
||||
|
||||
private fun contentFlow(portfolio: PortfoliosWithThisCurrency): Flow<MyPortfolioUM.Content> {
|
||||
fun Portfolio.actionsFoAccountCurrencies(): List<Flow<Pair<CryptoCurrency, TokenActionsState>>> =
|
||||
accountsWithAdded.map { account ->
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.features.account.api)
|
||||
implementation(projects.features.wallet.api)
|
||||
implementation(projects.features.walletconnect.api)
|
||||
implementation(projects.features.sendV2.api)
|
||||
|
|
@ -28,6 +29,7 @@ dependencies {
|
|||
implementation(projects.core.ui)
|
||||
|
||||
/** Domain models */
|
||||
implementation(projects.domain.account)
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
implementation(projects.domain.balanceHiding.models)
|
||||
implementation(projects.domain.blockaid.models)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
|||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.features.account.PortfolioSelectorComponent
|
||||
import com.tangem.features.walletconnect.connections.components.WcSelectNetworksComponent.*
|
||||
import com.tangem.features.walletconnect.connections.components.WcSelectWalletComponent.*
|
||||
import com.tangem.features.walletconnect.connections.model.WcPairModel
|
||||
import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes
|
||||
import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes.Alert
|
||||
|
|
@ -24,6 +27,7 @@ import com.tangem.features.walletconnect.connections.utils.WcAlertsFactory
|
|||
|
||||
internal class WcPairComponent(
|
||||
private val appComponentContext: AppComponentContext,
|
||||
private val portfolioSelectorComponentFactory: PortfolioSelectorComponent.Factory,
|
||||
params: Params,
|
||||
) : AppComponentContext by appComponentContext, ComposableContentComponent {
|
||||
|
||||
|
|
@ -65,6 +69,7 @@ internal class WcPairComponent(
|
|||
}
|
||||
is WcAppInfoRoutes.SelectNetworks,
|
||||
is WcAppInfoRoutes.SelectWallet,
|
||||
is WcAppInfoRoutes.PortfolioSelector,
|
||||
-> model.stackNavigation.pop()
|
||||
}
|
||||
}
|
||||
|
|
@ -107,6 +112,14 @@ internal class WcPairComponent(
|
|||
callback = model,
|
||||
),
|
||||
)
|
||||
WcAppInfoRoutes.PortfolioSelector -> portfolioSelectorComponentFactory.create(
|
||||
context = appComponentContext,
|
||||
params = PortfolioSelectorComponent.Params(
|
||||
portfolioFetcher = model.portfolioFetcher!!,
|
||||
bsCallback = model.portfolioSelectorCallback,
|
||||
controller = model.selectorController,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.walletconnect.connections.entity
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.common.ui.account.PortfolioSelectUM
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
|
@ -17,6 +18,7 @@ internal sealed class WcAppInfoUM : TangemBottomSheetConfigContent {
|
|||
data class Loading(
|
||||
override val onDismiss: () -> Unit,
|
||||
override val connectButtonConfig: WcPrimaryButtonConfig,
|
||||
val portfolioName: TextReference,
|
||||
) : WcAppInfoUM()
|
||||
|
||||
data class Content(
|
||||
|
|
@ -25,6 +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 networksInfo: WcNetworksInfo,
|
||||
|
|
|
|||
|
|
@ -5,17 +5,27 @@ import com.arkivanov.decompose.router.stack.StackNavigation
|
|||
import com.arkivanov.decompose.router.stack.pop
|
||||
import com.arkivanov.decompose.router.stack.pushNew
|
||||
import com.domain.blockaid.models.dapp.CheckDAppResult
|
||||
import com.tangem.common.ui.account.CryptoPortfolioIconUM
|
||||
import com.tangem.common.ui.account.PortfolioSelectUM
|
||||
import com.tangem.common.ui.account.toUM
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
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.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.message.SnackbarMessage
|
||||
import com.tangem.core.ui.message.ToastMessage
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
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
|
||||
|
|
@ -31,6 +41,9 @@ 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
|
||||
|
|
@ -40,7 +53,9 @@ import com.tangem.features.walletconnect.connections.model.transformers.*
|
|||
import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
import kotlin.properties.Delegates
|
||||
import com.tangem.utils.transformer.update as transformerUpdate
|
||||
|
|
@ -53,12 +68,17 @@ private const val WC_WALLETS_SELECTOR_MIN_COUNT = 2
|
|||
|
||||
@Stable
|
||||
@ModelScoped
|
||||
@Suppress("LongParameterList")
|
||||
@Suppress("LongParameterList", "LargeClass")
|
||||
internal class WcPairModel @Inject constructor(
|
||||
private val router: Router,
|
||||
private val messageSender: UiMessageSender,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val analytics: AnalyticsEventHandler,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
val selectorController: PortfolioSelectorController,
|
||||
private val singleAccountListSupplier: SingleAccountListSupplier,
|
||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
portfolioFetcherFactory: PortfolioFetcher.Factory,
|
||||
wcPairUseCaseFactory: WcPairUseCase.Factory,
|
||||
getWalletsUseCase: GetWalletsUseCase,
|
||||
paramsContainer: ParamsContainer,
|
||||
|
|
@ -74,10 +94,19 @@ internal class WcPairModel @Inject constructor(
|
|||
)
|
||||
|
||||
val stackNavigation = StackNavigation<WcAppInfoRoutes>()
|
||||
val portfolioFetcher: PortfolioFetcher?
|
||||
val portfolioSelectorCallback = object : PortfolioSelectorComponent.BottomSheetCallback {
|
||||
override val onDismiss: () -> Unit = { stackNavigation.pop() }
|
||||
override val onBack: () -> Unit = { stackNavigation.pop() }
|
||||
}
|
||||
|
||||
private val selectedUserWalletFlow: MutableStateFlow<UserWallet> by lazy {
|
||||
MutableStateFlow(getWalletsUseCase.invokeSync().first { it.walletId == params.userWalletId })
|
||||
}
|
||||
private val selectedPortfolio = MutableSharedFlow<Pair<UserWallet, AccountStatus>>(
|
||||
replay = 1,
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST,
|
||||
)
|
||||
private var proposalNetwork by Delegates.notNull<WcSessionProposal.ProposalNetwork>()
|
||||
private var sessionProposal by Delegates.notNull<WcSessionProposal>()
|
||||
private var additionallyEnabledNetworks = setOf<Network>()
|
||||
|
|
@ -87,75 +116,180 @@ internal class WcPairModel @Inject constructor(
|
|||
field = MutableStateFlow<WcAppInfoUM>(createLoadingState())
|
||||
|
||||
init {
|
||||
loadDAppInfo()
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
portfolioFetcher = portfolioFetcherFactory.create(
|
||||
mode = PortfolioFetcher.Mode.All(onlyMultiCurrency = true),
|
||||
scope = modelScope,
|
||||
)
|
||||
modelScope.launch {
|
||||
val params = SingleAccountListProducer.Params(params.userWalletId)
|
||||
val accountList = singleAccountListSupplier.getSyncOrNull(params)
|
||||
if (accountList == null) {
|
||||
router.pop()
|
||||
return@launch
|
||||
}
|
||||
val firstAccount = accountList.accounts.first()
|
||||
selectorController.selectAccount(firstAccount.accountId)
|
||||
combineFlows(portfolioFetcher)
|
||||
}
|
||||
} else {
|
||||
portfolioFetcher = null
|
||||
loadDAppInfo()
|
||||
}
|
||||
}
|
||||
|
||||
private fun combineFlows(portfolioFetcher: PortfolioFetcher) {
|
||||
combine(
|
||||
flow = portfolioFetcher.data,
|
||||
flow2 = selectorController.selectedAccountWithData(portfolioFetcher)
|
||||
.distinctUntilChanged()
|
||||
.filterNotNull()
|
||||
.onEach { selectedPortfolio.tryEmit(it) }
|
||||
.onEach { stackNavigation.pop() },
|
||||
flow3 = wcPairUseCase(),
|
||||
flow4 = isAccountsModeEnabledUseCase(),
|
||||
transform = { portfolios, selected, pairState, isAccountMode ->
|
||||
handlePairState(
|
||||
pairState,
|
||||
portfolios,
|
||||
selected,
|
||||
isAccountMode,
|
||||
)
|
||||
},
|
||||
)
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun loadDAppInfo() {
|
||||
wcPairUseCase()
|
||||
.onEach { pairState ->
|
||||
when (pairState) {
|
||||
is WcPairState.Approving.Loading -> appInfoUiState.transformerUpdate(
|
||||
WcConnectButtonProgressTransformer(showProgress = true),
|
||||
)
|
||||
is WcPairState.Approving.Result -> {
|
||||
appInfoUiState.transformerUpdate(
|
||||
WcConnectButtonProgressTransformer(showProgress = false),
|
||||
)
|
||||
pairState
|
||||
.result
|
||||
.onLeft(::processError)
|
||||
.onRight(::processSuccessfullyConnected)
|
||||
router.pop()
|
||||
}
|
||||
is WcPairState.Error -> {
|
||||
appInfoUiState.transformerUpdate(
|
||||
WcConnectButtonProgressTransformer(showProgress = false),
|
||||
)
|
||||
processError(pairState.error)
|
||||
}
|
||||
is WcPairState.Loading -> appInfoUiState.update { createLoadingState() }
|
||||
is WcPairState.Proposal -> {
|
||||
val availableWallets = pairState.dAppSession.proposalNetwork.keys
|
||||
.filter { !it.isLocked && it.isMultiCurrency }
|
||||
sessionProposal = pairState.dAppSession
|
||||
val foundNetwork = sessionProposal.proposalNetwork[selectedUserWalletFlow.value]
|
||||
if (foundNetwork == null) {
|
||||
processError(Unknown("Selected wallet not found"))
|
||||
} else {
|
||||
proposalNetwork = foundNetwork
|
||||
additionallyEnabledNetworks = proposalNetwork.available
|
||||
appInfoUiState.transformerUpdate(
|
||||
WcAppInfoTransformer(
|
||||
dAppSession = sessionProposal,
|
||||
dAppVerifiedStateConverter = dAppVerifiedStateConverter,
|
||||
onDismiss = ::rejectPairing,
|
||||
onConnect = ::onConnect,
|
||||
onWalletClick = {
|
||||
stackNavigation.pushNew(
|
||||
WcAppInfoRoutes.SelectWallet(selectedUserWalletFlow.value.walletId),
|
||||
)
|
||||
}.takeIf { availableWallets.size >= WC_WALLETS_SELECTOR_MIN_COUNT },
|
||||
onNetworksClick = {
|
||||
stackNavigation.pushNew(
|
||||
WcAppInfoRoutes.SelectNetworks(
|
||||
missingRequiredNetworks = proposalNetwork.missingRequired,
|
||||
requiredNetworks = proposalNetwork.required,
|
||||
availableNetworks = proposalNetwork.available,
|
||||
enabledAvailableNetworks = additionallyEnabledNetworks,
|
||||
notAddedNetworks = proposalNetwork.notAdded,
|
||||
),
|
||||
)
|
||||
},
|
||||
userWallet = selectedUserWalletFlow.value,
|
||||
proposalNetwork = proposalNetwork,
|
||||
additionallyEnabledNetworks = additionallyEnabledNetworks,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
.onEach { pairState -> handlePairState(pairState) }
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private suspend fun handlePairState(
|
||||
pairState: WcPairState,
|
||||
portfolios: PortfolioFetcher.Data? = null,
|
||||
selected: Pair<UserWallet, AccountStatus>? = null,
|
||||
isAccountMode: Boolean? = null,
|
||||
) {
|
||||
when (pairState) {
|
||||
is WcPairState.Approving.Loading -> appInfoUiState.transformerUpdate(
|
||||
WcConnectButtonProgressTransformer(showProgress = true),
|
||||
)
|
||||
is WcPairState.Approving.Result -> {
|
||||
appInfoUiState.transformerUpdate(
|
||||
WcConnectButtonProgressTransformer(showProgress = false),
|
||||
)
|
||||
pairState
|
||||
.result
|
||||
.onLeft(::processError)
|
||||
.onRight(::processSuccessfullyConnected)
|
||||
router.pop()
|
||||
}
|
||||
is WcPairState.Error -> {
|
||||
appInfoUiState.transformerUpdate(
|
||||
WcConnectButtonProgressTransformer(showProgress = false),
|
||||
)
|
||||
processError(pairState.error)
|
||||
}
|
||||
is WcPairState.Loading -> appInfoUiState.update { createLoadingState(isAccountMode ?: false) }
|
||||
is WcPairState.Proposal -> handleProposalState(
|
||||
pairState = pairState,
|
||||
portfolios = portfolios,
|
||||
selected = selected,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleProposalState(
|
||||
pairState: WcPairState.Proposal,
|
||||
portfolios: PortfolioFetcher.Data? = null,
|
||||
selected: Pair<UserWallet, AccountStatus>? = null,
|
||||
) {
|
||||
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 proposalAccountNetwork = sessionProposal.proposalAccountNetwork
|
||||
val foundNetwork = if (portfolioAccountId != null) {
|
||||
requireNotNull(proposalAccountNetwork)[portfolioAccountId]
|
||||
} else {
|
||||
sessionProposal.proposalNetwork[selectedUserWalletFlow.value]
|
||||
}
|
||||
if (foundNetwork == null) {
|
||||
processError(Unknown("Selected wallet not found"))
|
||||
} else {
|
||||
val portfolioSelectRow = tryToCreatePortfolioSelectRow(selected, portfolios)
|
||||
if (proposalAccountNetwork != null) {
|
||||
selectorController.isEnabled.value = { wallet, account ->
|
||||
proposalAccountNetwork.contains(account.account.accountId)
|
||||
}
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
proposalNetwork = foundNetwork
|
||||
additionallyEnabledNetworks = proposalNetwork.available
|
||||
appInfoUiState.transformerUpdate(
|
||||
WcAppInfoTransformer(
|
||||
dAppSession = sessionProposal,
|
||||
dAppVerifiedStateConverter = dAppVerifiedStateConverter,
|
||||
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(
|
||||
missingRequiredNetworks = proposalNetwork.missingRequired,
|
||||
requiredNetworks = proposalNetwork.required,
|
||||
availableNetworks = proposalNetwork.available,
|
||||
enabledAvailableNetworks = additionallyEnabledNetworks,
|
||||
notAddedNetworks = proposalNetwork.notAdded,
|
||||
),
|
||||
)
|
||||
},
|
||||
userWallet = portfolioWallet ?: selectedUserWalletFlow.value,
|
||||
proposalNetwork = proposalNetwork,
|
||||
additionallyEnabledNetworks = additionallyEnabledNetworks,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun tryToCreatePortfolioSelectRow(
|
||||
selectedPortfolio: Pair<UserWallet, AccountStatus>?,
|
||||
portfolios: PortfolioFetcher.Data?,
|
||||
): PortfolioSelectUM? {
|
||||
selectedPortfolio ?: return null
|
||||
portfolios ?: return null
|
||||
val (wallet, portfolioAccount) = selectedPortfolio
|
||||
val account = when (val account = portfolioAccount.account) {
|
||||
is Account.CryptoPortfolio -> account
|
||||
}
|
||||
val isAccountMode = selectorController.isAccountMode.first()
|
||||
val icon: CryptoPortfolioIconUM?
|
||||
val name: TextReference
|
||||
if (isAccountMode) {
|
||||
icon = account.icon.toUM()
|
||||
name = account.accountName.toUM().value
|
||||
} else {
|
||||
icon = null
|
||||
name = stringReference(wallet.name)
|
||||
}
|
||||
return PortfolioSelectUM(
|
||||
icon = icon,
|
||||
name = name,
|
||||
isAccountMode = selectorController.isAccountMode.first(),
|
||||
isMultiChoice = !portfolios.isSingleChoice,
|
||||
onClick = { stackNavigation.pushNew(WcAppInfoRoutes.PortfolioSelector) },
|
||||
)
|
||||
}
|
||||
|
||||
fun rejectPairing() {
|
||||
|
|
@ -182,11 +316,14 @@ 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
|
||||
wcPairUseCase.approve(
|
||||
WcSessionApprove(
|
||||
wallet = selectedUserWalletFlow.value,
|
||||
wallet = wallet,
|
||||
network = enabledAvailableNetworks + proposalNetwork.required,
|
||||
account = null, // todo account
|
||||
account = account,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -269,10 +406,15 @@ internal class WcPairModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun createLoadingState(): WcAppInfoUM.Loading {
|
||||
private fun createLoadingState(isAccountMode: Boolean = false): WcAppInfoUM.Loading {
|
||||
return WcAppInfoUM.Loading(
|
||||
onDismiss = ::rejectPairing,
|
||||
connectButtonConfig = WcPrimaryButtonConfig(showProgress = false, enabled = false, onClick = {}),
|
||||
portfolioName = if (isAccountMode) {
|
||||
resourceReference(R.string.account_details_title)
|
||||
} else {
|
||||
resourceReference(R.string.wc_common_wallet)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
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
|
||||
|
|
@ -15,6 +16,7 @@ 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 onNetworksClick: () -> Unit,
|
||||
private val userWallet: UserWallet,
|
||||
|
|
@ -33,6 +35,7 @@ internal class WcAppInfoTransformer(
|
|||
notification = createNotification(dAppSession.securityStatus),
|
||||
walletName = userWallet.name,
|
||||
onWalletClick = onWalletClick,
|
||||
portfolioSelectRow = portfolioSelectRow,
|
||||
networksInfo = WcNetworksInfoConverter.convert(
|
||||
value = WcNetworksInfoConverter.Input(
|
||||
missingNetworks = proposalNetwork.missingRequired,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ internal sealed class WcAppInfoRoutes : Route {
|
|||
@Serializable
|
||||
data object AppInfo : WcAppInfoRoutes()
|
||||
|
||||
@Serializable
|
||||
data object PortfolioSelector : WcAppInfoRoutes()
|
||||
|
||||
@Serializable
|
||||
data class SelectWallet(val selectedWalletId: UserWalletId) : WcAppInfoRoutes()
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.tangem.core.decompose.context.AppComponentContext
|
|||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.features.account.PortfolioSelectorComponent
|
||||
import com.tangem.features.send.v2.api.FeeSelectorBlockComponent
|
||||
import com.tangem.features.send.v2.api.FeeSelectorComponent
|
||||
import com.tangem.features.walletconnect.components.WcRoutingComponent
|
||||
|
|
@ -34,6 +35,7 @@ internal class DefaultWcRoutingComponent @AssistedInject constructor(
|
|||
@Assisted private val appComponentContext: AppComponentContext,
|
||||
@Assisted params: Unit,
|
||||
private val feeSelectorBlockComponentFactory: FeeSelectorBlockComponent.Factory,
|
||||
private val portfolioSelectorComponentFactory: PortfolioSelectorComponent.Factory,
|
||||
private val feeSelectorComponentFactory: FeeSelectorComponent.Factory,
|
||||
) : AppComponentContext by appComponentContext, WcRoutingComponent {
|
||||
|
||||
|
|
@ -85,6 +87,7 @@ internal class DefaultWcRoutingComponent @AssistedInject constructor(
|
|||
)
|
||||
is WcInnerRoute.Pair -> WcPairComponent(
|
||||
appComponentContext = childContext,
|
||||
portfolioSelectorComponentFactory = portfolioSelectorComponentFactory,
|
||||
params = WcPairComponent.Params(
|
||||
userWalletId = config.request.userWalletId,
|
||||
wcUrl = config.request.uri,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.account.PortfolioSelectRow
|
||||
import com.tangem.common.ui.account.PortfolioSelectRowPreviewData
|
||||
import com.tangem.common.ui.account.PortfolioSelectUM
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
|
|
@ -36,10 +39,7 @@ import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTi
|
|||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetWithFooter
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.extensions.clickableSingle
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -87,7 +87,7 @@ internal fun WcAppInfoModalBottomSheet(state: WcAppInfoUM, onBack: () -> Unit, o
|
|||
private fun WcAppInfoModalBottomSheet(state: WcAppInfoUM, modifier: Modifier = Modifier) {
|
||||
when (state) {
|
||||
is WcAppInfoUM.Content -> WcAppInfoModalBottomSheetContent(state, modifier)
|
||||
is WcAppInfoUM.Loading -> WcAppInfoModalBottomSheetLoading(modifier)
|
||||
is WcAppInfoUM.Loading -> WcAppInfoModalBottomSheetLoading(state, modifier)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -273,15 +273,19 @@ private fun WcAppInfoSecondBlock(state: WcAppInfoUM.Content, modifier: Modifier
|
|||
val itemsModifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(TangemTheme.dimens.spacing12)
|
||||
WalletRowItem(
|
||||
modifier = if (state.onWalletClick != null) {
|
||||
Modifier.clickableSingle(onClick = state.onWalletClick)
|
||||
} else {
|
||||
Modifier
|
||||
}.then(itemsModifier),
|
||||
walletName = state.walletName,
|
||||
showEndIcon = state.onWalletClick != null,
|
||||
)
|
||||
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,
|
||||
)
|
||||
}
|
||||
HorizontalDivider(thickness = 1.dp, color = TangemTheme.colors.stroke.primary)
|
||||
SelectNetworksBlock(
|
||||
modifier = Modifier
|
||||
|
|
@ -322,6 +326,21 @@ private fun WcAppInfoSecondBlock(state: WcAppInfoUM.Content, modifier: Modifier
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PortfolioRowItem(portfolioSelectRow: PortfolioSelectUM, modifier: Modifier = Modifier) {
|
||||
PortfolioSelectRow(modifier = modifier, state = portfolioSelectRow) {
|
||||
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,
|
||||
)
|
||||
SpacerW4()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WalletRowItem(walletName: String, showEndIcon: Boolean, modifier: Modifier = Modifier) {
|
||||
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
|
||||
|
|
@ -494,7 +513,7 @@ private fun WcAppInfoButtons(
|
|||
|
||||
// region Loading state
|
||||
@Composable
|
||||
private fun WcAppInfoModalBottomSheetLoading(modifier: Modifier = Modifier) {
|
||||
private fun WcAppInfoModalBottomSheetLoading(state: WcAppInfoUM.Loading, modifier: Modifier = Modifier) {
|
||||
Column(modifier = modifier) {
|
||||
val blocksModifier = Modifier
|
||||
.clip(RoundedCornerShape(TangemTheme.dimens.radius14))
|
||||
|
|
@ -502,6 +521,7 @@ private fun WcAppInfoModalBottomSheetLoading(modifier: Modifier = Modifier) {
|
|||
.fillMaxWidth()
|
||||
WcAppInfoFirstLoadingBlock(blocksModifier)
|
||||
WcAppInfoSecondLoadingBlock(
|
||||
portfolioName = state.portfolioName,
|
||||
modifier = Modifier
|
||||
.padding(top = 14.dp)
|
||||
.then(blocksModifier),
|
||||
|
|
@ -535,7 +555,7 @@ private fun WcAppInfoFirstLoadingBlock(modifier: Modifier = Modifier) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun WcAppInfoSecondLoadingBlock(modifier: Modifier = Modifier) {
|
||||
private fun WcAppInfoSecondLoadingBlock(portfolioName: TextReference, modifier: Modifier = Modifier) {
|
||||
Column(modifier) {
|
||||
Row(modifier = Modifier.padding(all = 12.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
|
|
@ -546,9 +566,9 @@ private fun WcAppInfoSecondLoadingBlock(modifier: Modifier = Modifier) {
|
|||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(start = 8.dp)
|
||||
.padding(start = 4.dp)
|
||||
.weight(1f),
|
||||
text = stringResourceSafe(R.string.wc_common_wallet),
|
||||
text = portfolioName.resolveReference(),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
|
|
@ -564,7 +584,7 @@ private fun WcAppInfoSecondLoadingBlock(modifier: Modifier = Modifier) {
|
|||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(start = 8.dp)
|
||||
.padding(start = 4.dp)
|
||||
.weight(1f),
|
||||
text = stringResourceSafe(R.string.wc_common_networks),
|
||||
style = TangemTheme.typography.body1,
|
||||
|
|
@ -642,7 +662,11 @@ private fun WcAppInfoBottomSheetPreview(@PreviewParameter(WcAppInfoStateProvider
|
|||
|
||||
private class WcAppInfoStateProvider : CollectionPreviewParameterProvider<WcAppInfoUM>(
|
||||
collection = listOf(
|
||||
WcAppInfoUM.Loading(onDismiss = {}, WcPrimaryButtonConfig(showProgress = false, enabled = false, onClick = {})),
|
||||
WcAppInfoUM.Loading(
|
||||
onDismiss = {},
|
||||
portfolioName = stringReference("Wallet"),
|
||||
connectButtonConfig = WcPrimaryButtonConfig(showProgress = false, enabled = false, onClick = {}),
|
||||
),
|
||||
WcAppInfoUM.Content(
|
||||
appName = "React App",
|
||||
appIcon = "",
|
||||
|
|
@ -651,6 +675,7 @@ private class WcAppInfoStateProvider : CollectionPreviewParameterProvider<WcAppI
|
|||
notification = WcAppInfoSecurityNotification.SecurityRisk,
|
||||
walletName = "Tangem 2.0 Tangem 2.0 Tangem 2.0 Tangem 2.0",
|
||||
onWalletClick = null,
|
||||
portfolioSelectRow = null,
|
||||
networksInfo = WcNetworksInfo.ContainsAllRequiredNetworks(
|
||||
items = persistentListOf(
|
||||
WcNetworkInfoItem.Required(
|
||||
|
|
@ -695,6 +720,21 @@ private class WcAppInfoStateProvider : CollectionPreviewParameterProvider<WcAppI
|
|||
verifiedDAppState = VerifiedDAppState.Unknown,
|
||||
appSubtitle = "react-app.walletconnect.com",
|
||||
notification = WcAppInfoSecurityNotification.UnknownDomain,
|
||||
portfolioSelectRow = null,
|
||||
walletName = "Tangem 2.0 Tangem 2.0 Tangem 2.0 Tangem 2.0",
|
||||
onWalletClick = {},
|
||||
networksInfo = WcNetworksInfo.MissingRequiredNetworkInfo(networks = "Solana"),
|
||||
onNetworksClick = {},
|
||||
onDismiss = {},
|
||||
connectButtonConfig = WcPrimaryButtonConfig(showProgress = false, enabled = true, onClick = {}),
|
||||
),
|
||||
WcAppInfoUM.Content(
|
||||
appName = "React App",
|
||||
appIcon = "",
|
||||
verifiedDAppState = VerifiedDAppState.Unknown,
|
||||
appSubtitle = "react-app.walletconnect.com",
|
||||
notification = WcAppInfoSecurityNotification.UnknownDomain,
|
||||
portfolioSelectRow = PortfolioSelectRowPreviewData.account,
|
||||
walletName = "Tangem 2.0 Tangem 2.0 Tangem 2.0 Tangem 2.0",
|
||||
onWalletClick = {},
|
||||
networksInfo = WcNetworksInfo.MissingRequiredNetworkInfo(networks = "Solana"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue