Updated on 2026-08-14
This commit is contained in:
commit
63133bb8fb
117 changed files with 1915 additions and 1265 deletions
|
|
@ -10,7 +10,6 @@ import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
|||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -70,7 +69,6 @@ internal object ManageTokensDomainModule {
|
|||
customTokensRepository: CustomTokensRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
derivationsRepository: DerivationsRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
|
|
@ -83,7 +81,6 @@ internal object ManageTokensDomainModule {
|
|||
customTokensRepository = customTokensRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
currenciesRepository = currenciesRepository,
|
||||
networksRepository = networksRepository,
|
||||
derivationsRepository = derivationsRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
|||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import dagger.Module
|
||||
|
|
@ -70,7 +69,6 @@ object MarketsDomainModule {
|
|||
derivationsRepository: DerivationsRepository,
|
||||
marketsTokenRepository: MarketsTokenRepository,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
|
|
@ -82,7 +80,6 @@ object MarketsDomainModule {
|
|||
derivationsRepository = derivationsRepository,
|
||||
marketsTokenRepository = marketsTokenRepository,
|
||||
currenciesRepository = currenciesRepository,
|
||||
networksRepository = networksRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ internal object TokensDomainModule {
|
|||
@Singleton
|
||||
fun provideAddCryptoCurrenciesUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
|
|
@ -47,7 +46,6 @@ internal object TokensDomainModule {
|
|||
): AddCryptoCurrenciesUseCase {
|
||||
return AddCryptoCurrenciesUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
networksRepository = networksRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
|
|
@ -62,7 +60,6 @@ internal object TokensDomainModule {
|
|||
fun provideFetchTokenListUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
multiQuoteFetcher: MultiQuoteFetcher,
|
||||
|
|
@ -71,7 +68,6 @@ internal object TokensDomainModule {
|
|||
): FetchTokenListUseCase {
|
||||
return FetchTokenListUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
networksRepository = networksRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
|
|
@ -121,8 +117,8 @@ internal object TokensDomainModule {
|
|||
fun provideGetCurrencyUseCase(
|
||||
baseCurrencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): GetCurrencyStatusUpdatesUseCase {
|
||||
return GetCurrencyStatusUpdatesUseCase(
|
||||
): GetSingleCryptoCurrencyStatusUseCase {
|
||||
return GetSingleCryptoCurrencyStatusUseCase(
|
||||
currencyStatusOperations = baseCurrencyStatusOperations,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
|
|
@ -162,24 +158,11 @@ internal object TokensDomainModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetPrimaryCurrencyUseCase(
|
||||
currencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): GetPrimaryCurrencyStatusUpdatesUseCase {
|
||||
return GetPrimaryCurrencyStatusUpdatesUseCase(
|
||||
currencyStatusOperations = currencyStatusOperations,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideFetchCurrencyStatusUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
multiQuoteFetcher: MultiQuoteFetcher,
|
||||
|
|
@ -188,7 +171,6 @@ internal object TokensDomainModule {
|
|||
): FetchCurrencyStatusUseCase {
|
||||
return FetchCurrencyStatusUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
networksRepository = networksRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
|
||||
|
|
@ -203,7 +185,6 @@ internal object TokensDomainModule {
|
|||
fun provideFetchCardTokenListUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
multiQuoteFetcher: MultiQuoteFetcher,
|
||||
|
|
@ -212,7 +193,6 @@ internal object TokensDomainModule {
|
|||
): FetchCardTokenListUseCase {
|
||||
return FetchCardTokenListUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
networksRepository = networksRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
|
|
@ -222,14 +202,6 @@ internal object TokensDomainModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesGetCryptoCurrencyStatusSyncUseCase(
|
||||
currencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
): GetCryptoCurrencyStatusSyncUseCase {
|
||||
return GetCryptoCurrencyStatusSyncUseCase(currencyStatusOperations)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetCryptoCurrencyUseCase(currenciesRepository: CurrenciesRepository): GetCryptoCurrencyUseCase {
|
||||
|
|
@ -328,14 +300,10 @@ internal object TokensDomainModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideUpdateDelayedCurrencyStatusUseCase(
|
||||
networksRepository: NetworksRepository,
|
||||
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): UpdateDelayedNetworkStatusUseCase {
|
||||
return UpdateDelayedNetworkStatusUseCase(
|
||||
networksRepository = networksRepository,
|
||||
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -413,7 +381,6 @@ internal object TokensDomainModule {
|
|||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
quotesRepositoryV2: QuotesRepositoryV2,
|
||||
networksRepository: NetworksRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
|
|
@ -427,7 +394,6 @@ internal object TokensDomainModule {
|
|||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
quotesRepositoryV2 = quotesRepositoryV2,
|
||||
networksRepository = networksRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
|
|
@ -447,7 +413,6 @@ internal object TokensDomainModule {
|
|||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
quotesRepositoryV2: QuotesRepositoryV2,
|
||||
networksRepository: NetworksRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
|
|
@ -461,7 +426,6 @@ internal object TokensDomainModule {
|
|||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
quotesRepositoryV2 = quotesRepositoryV2,
|
||||
networksRepository = networksRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@ import com.tangem.domain.card.repository.CardSdkConfigRepository
|
|||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
|
||||
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.transaction.FeeRepository
|
||||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.usecase.*
|
||||
|
|
@ -43,7 +41,6 @@ internal object TransactionDomainModule {
|
|||
transactionRepository: TransactionRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): SendTransactionUseCase {
|
||||
return SendTransactionUseCase(
|
||||
demoConfig = DemoConfig(),
|
||||
|
|
@ -51,7 +48,6 @@ internal object TransactionDomainModule {
|
|||
transactionRepository = transactionRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -61,17 +57,13 @@ internal object TransactionDomainModule {
|
|||
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): AssociateAssetUseCase {
|
||||
return AssociateAssetUseCase(
|
||||
cardSdkConfigRepository = cardSdkConfigRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
currenciesRepository = currenciesRepository,
|
||||
networksRepository = networksRepository,
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@ internal class DefaultTokensFeatureToggles(
|
|||
private val featureTogglesManager: FeatureTogglesManager,
|
||||
) : TokensFeatureToggles {
|
||||
|
||||
override val isNetworksLoadingRefactoringEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(name = "NETWORKS_LOADING_REFACTORING_ENABLED")
|
||||
|
||||
override val isQuotesLoadingRefactoringEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(name = "QUOTES_LOADING_REFACTORING_ENABLED")
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.domain.walletconnect.WcPairService
|
|||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.walletconnect.model.legacy.Account
|
||||
import com.tangem.domain.walletconnect.usecase.initialize.WcInitializeUseCase
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.walletconnect.components.WalletConnectFeatureToggles
|
||||
import com.tangem.tap.common.analytics.events.WalletConnect
|
||||
import com.tangem.tap.domain.walletconnect2.app.TangemWcBlockchainHelper
|
||||
|
|
@ -64,14 +65,18 @@ internal class DefaultLegacyWalletConnectRepositoryFacade constructor(
|
|||
if (isNewWc) stub.updateSessions() else legacy.updateSessions()
|
||||
}
|
||||
|
||||
override fun pair(uri: String, source: SourceType) {
|
||||
override fun pair(userWalletId: UserWalletId, uri: String, source: SourceType) {
|
||||
val src = when (source) {
|
||||
SourceType.QR -> WcPairRequest.Source.QR
|
||||
SourceType.DEEPLINK -> WcPairRequest.Source.DEEPLINK
|
||||
SourceType.CLIPBOARD -> WcPairRequest.Source.CLIPBOARD
|
||||
SourceType.ETC -> WcPairRequest.Source.ETC
|
||||
}
|
||||
if (isNewWc) wcPairService.pair(WcPairRequest(uri, src)) else legacy.pair(uri, source)
|
||||
if (isNewWc) {
|
||||
wcPairService.pair(WcPairRequest(uri = uri, source = src, userWalletId = userWalletId))
|
||||
} else {
|
||||
legacy.pair(userWalletId = userWalletId, uri = uri, source = source)
|
||||
}
|
||||
}
|
||||
|
||||
override fun disconnect(topic: String) {
|
||||
|
|
@ -110,7 +115,7 @@ internal class LegacyWalletConnectRepositoryStub : LegacyWalletConnectRepository
|
|||
|
||||
override fun updateSessions() = Unit
|
||||
|
||||
override fun pair(uri: String, source: SourceType) = Unit
|
||||
override fun pair(userWalletId: UserWalletId, uri: String, source: SourceType) = Unit
|
||||
|
||||
override fun disconnect(topic: String) = Unit
|
||||
|
||||
|
|
@ -405,7 +410,7 @@ internal class DefaultLegacyWalletConnectRepository(
|
|||
this.userNamespaces = userNamespaces
|
||||
}
|
||||
|
||||
override fun pair(uri: String, source: SourceType) {
|
||||
override fun pair(userWalletId: UserWalletId, uri: String, source: SourceType) {
|
||||
analyticsHandler.send(WalletConnect.NewSessionInitiated(source = source))
|
||||
WalletKit.pair(
|
||||
params = Wallet.Params.Pair(uri),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.domain.walletconnect2.domain
|
||||
|
||||
import com.tangem.domain.walletconnect.model.legacy.Account
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.*
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction.OpenSession.SourceType
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -19,7 +20,7 @@ interface LegacyWalletConnectRepository {
|
|||
|
||||
fun updateSessions()
|
||||
|
||||
fun pair(uri: String, source: SourceType)
|
||||
fun pair(userWalletId: UserWalletId, uri: String, source: SourceType)
|
||||
|
||||
fun disconnect(topic: String)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.domain.walletconnect.model.legacy.WalletConnectSessionsReposit
|
|||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.filterNotNull
|
||||
|
|
@ -139,7 +140,11 @@ class WalletConnectInteractor(
|
|||
if (deeplinkStack.empty()) return
|
||||
val lastDeeplink = deeplinkStack.pop()
|
||||
val action = WalletConnectAction
|
||||
.OpenSession(lastDeeplink, WalletConnectAction.OpenSession.SourceType.DEEPLINK)
|
||||
.OpenSession(
|
||||
wcUri = lastDeeplink,
|
||||
source = WalletConnectAction.OpenSession.SourceType.DEEPLINK,
|
||||
userWalletId = UserWalletId(userWalletId),
|
||||
)
|
||||
store.dispatchOnMain(action)
|
||||
}.onFailure {
|
||||
Timber.e("WC deeplink handling failed. $it")
|
||||
|
|
@ -393,7 +398,11 @@ class WalletConnectInteractor(
|
|||
}
|
||||
|
||||
if (isWalletConnectReadyForDeepLinks) {
|
||||
val action = WalletConnectAction.OpenSession(deeplink, WalletConnectAction.OpenSession.SourceType.DEEPLINK)
|
||||
val action = WalletConnectAction.OpenSession(
|
||||
wcUri = deeplink,
|
||||
source = WalletConnectAction.OpenSession.SourceType.DEEPLINK,
|
||||
userWalletId = UserWalletId(userWalletId),
|
||||
)
|
||||
store.dispatchOnMain(action)
|
||||
} else {
|
||||
deeplinkStack.push(deeplink)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.features.details.redux.walletconnect
|
||||
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WcPreparedRequest
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectError
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectEvents
|
||||
|
|
@ -14,6 +15,7 @@ sealed class WalletConnectAction : Action {
|
|||
data class OpenSession(
|
||||
val wcUri: String,
|
||||
val source: SourceType,
|
||||
val userWalletId: UserWalletId,
|
||||
) : WalletConnectAction() {
|
||||
enum class SourceType { QR, DEEPLINK, CLIPBOARD, ETC }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,11 @@ class WalletConnectMiddleware {
|
|||
is WalletConnectAction.OpenSession -> {
|
||||
val index = action.wcUri.indexOf("@")
|
||||
when (action.wcUri[index + 1]) {
|
||||
'2' -> walletConnectRepository.pair(uri = action.wcUri, source = action.source)
|
||||
'2' -> walletConnectRepository.pair(
|
||||
uri = action.wcUri,
|
||||
source = action.source,
|
||||
userWalletId = action.userWalletId,
|
||||
)
|
||||
'1' -> {
|
||||
store.dispatchOnMain(WalletConnectAction.UnsupportedDappRequest)
|
||||
store.dispatchOnMain(
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ import org.rekotlin.StoreSubscriber
|
|||
@Suppress("UnusedPrivateMember")
|
||||
internal class DefaultWalletConnectComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted params: Unit,
|
||||
@Assisted params: WalletConnectComponent.Params,
|
||||
) : WalletConnectComponent, AppComponentContext by appComponentContext, StoreSubscriber<WalletConnectState> {
|
||||
|
||||
private val model: WalletConnectModel = getOrCreateModel()
|
||||
private val model: WalletConnectModel = getOrCreateModel(params)
|
||||
|
||||
private var screenState: MutableState<WalletConnectScreenState> =
|
||||
mutableStateOf(model.updateState(store.state.walletConnectState))
|
||||
|
|
@ -65,6 +65,9 @@ internal class DefaultWalletConnectComponent @AssistedInject constructor(
|
|||
|
||||
@AssistedFactory
|
||||
interface Factory : WalletConnectComponent.Factory {
|
||||
override fun create(context: AppComponentContext, params: Unit): DefaultWalletConnectComponent
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: WalletConnectComponent.Params,
|
||||
): DefaultWalletConnectComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -4,10 +4,12 @@ import androidx.compose.runtime.Stable
|
|||
import arrow.core.getOrElse
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState
|
||||
import com.tangem.tap.features.details.ui.walletconnect.api.WalletConnectComponent
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
@ -22,13 +24,22 @@ import javax.inject.Inject
|
|||
internal class WalletConnectModel @Inject constructor(
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<WalletConnectComponent.Params>()
|
||||
|
||||
init {
|
||||
modelScope.launch {
|
||||
listenToQrScanningUseCase(SourceType.WALLET_CONNECT)
|
||||
.getOrElse { emptyFlow() }
|
||||
.map { WalletConnectAction.OpenSession(it, WalletConnectAction.OpenSession.SourceType.QR) }
|
||||
.map {
|
||||
WalletConnectAction.OpenSession(
|
||||
wcUri = it,
|
||||
source = WalletConnectAction.OpenSession.SourceType.QR,
|
||||
userWalletId = params.userWalletId,
|
||||
)
|
||||
}
|
||||
.collect { store.dispatch(it) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ package com.tangem.tap.features.details.ui.walletconnect.api
|
|||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
interface WalletConnectComponent : ComposableContentComponent {
|
||||
interface Factory : ComponentFactory<Unit, WalletConnectComponent>
|
||||
data class Params(val userWalletId: UserWalletId)
|
||||
interface Factory : ComponentFactory<Params, WalletConnectComponent>
|
||||
}
|
||||
|
|
@ -291,13 +291,13 @@ internal class ChildFactory @Inject constructor(
|
|||
if (walletConnectFeatureToggles.isRedesignedWalletConnectEnabled) {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = Unit,
|
||||
params = RedesignedWalletConnectComponent.Params(route.userWalletId),
|
||||
componentFactory = redesignedWalletConnectComponentFactory,
|
||||
)
|
||||
} else {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = Unit,
|
||||
params = WalletConnectComponent.Params(route.userWalletId),
|
||||
componentFactory = walletConnectComponentFactory,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ sealed class AppRoute(val path: String) : Route {
|
|||
}
|
||||
|
||||
@Serializable
|
||||
data object WalletConnectSessions : AppRoute(path = "/wallet_connect_sessions")
|
||||
data class WalletConnectSessions(val userWalletId: UserWalletId) : AppRoute(path = "/wallet_connect_sessions")
|
||||
|
||||
@Serializable
|
||||
data class QrScanning(val source: Source) : AppRoute(path = "/$source/qr_scanning${source.path}") {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
},
|
||||
{
|
||||
"name": "NEW_ATTESTATION_ENABLED",
|
||||
"version": "undefined"
|
||||
"version": "5.24.0"
|
||||
},
|
||||
{
|
||||
"name": "SEND_V2_ENABLED",
|
||||
|
|
@ -51,10 +51,6 @@
|
|||
"name": "WALLET_CONNECT_REDESIGN_ENABLED",
|
||||
"version": "undefined"
|
||||
},
|
||||
{
|
||||
"name": "NETWORKS_LOADING_REFACTORING_ENABLED",
|
||||
"version": "5.23.0"
|
||||
},
|
||||
{
|
||||
"name": "QUOTES_LOADING_REFACTORING_ENABLED",
|
||||
"version": "5.24.0"
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@
|
|||
<string name="exchange_tokens_unavailable_tokens_header">Kann nicht gegen %s ausgetauscht werden</string>
|
||||
<string name="express_by_provider">Bereitgestellt von</string>
|
||||
<string name="express_cex_status_button_title">Status</string>
|
||||
<string name="express_choose_providers_subtitle">Tangem bietet Token-Swaps über Drittanbieter gemäß den jeweiligen Bedingungen des jeweiligen Anbieters an.</string>
|
||||
<string name="express_choose_providers_subtitle">Anbieter erleichtern Transaktionen</string>
|
||||
<string name="express_choose_providers_title">Anbieter</string>
|
||||
<string name="express_error_code">Es ist ein Fehler aufgetreten. Code: %s</string>
|
||||
<string name="express_error_provider_amount_roundup">Fehler %1$s. Der ausgewählte Anbieter kann die angegebene Transaktion nicht verarbeiten. Bitte runde den Wert auf %2$s auf oder änder diesen.</string>
|
||||
|
|
@ -319,11 +319,11 @@
|
|||
<string name="express_exchange_status_verifying">Verifizierung erforderlich</string>
|
||||
<string name="express_exchange_status_waiting_tx_hash">Wartet auf Transaktions-Hash</string>
|
||||
<string name="express_exchange_token_list_subtitle">Liste aller Token, die deiner Wallet hinzugefügt wurden</string>
|
||||
<string name="express_fetch_best_rates">Beste Preise werden abgerufen …</string>
|
||||
<string name="express_fetch_best_rates">Aktuelle Preise werden abgerufen ...</string>
|
||||
<string name="express_floating_rate">Variabler Zinssatz</string>
|
||||
<string name="express_legal_one_placeholder">Durch die Nutzung der Swap-Funktion erklärst du dich mit den folgenden Bedingungen des Anbieters einverstanden %s</string>
|
||||
<string name="express_legal_two_placeholders">Durch die Nutzung der Swap-Funktionalität erklärst du dich mit des Anbieters %1$s und %2$s einverstanden</string>
|
||||
<string name="express_more_providers_soon">Weitere Anbieter werden bald folgen.\nBleib dabei!</string>
|
||||
<string name="express_more_providers_soon">Weitere Anbieter folgen in Kürze</string>
|
||||
<string name="express_provider">Anbieter</string>
|
||||
<string name="express_provider_best_rate">Bester Preis</string>
|
||||
<string name="express_provider_max_amount">Verfügbar bis zu %s</string>
|
||||
|
|
@ -419,6 +419,7 @@
|
|||
<string name="markets_add_to_my_portfolio_unavailable_description">Dieses Asset wird derzeit in der Wallet nicht unterstützt.</string>
|
||||
<string name="markets_add_to_my_portfolio_unavailable_for_wallet_description">Dieses Asset ist für dieses Wallet nicht verfügbar</string>
|
||||
<string name="markets_add_token">Hinzufügen</string>
|
||||
<string name="markets_apy_placeholder">APY %s</string>
|
||||
<string name="markets_available_networks">Verfügbare Netzwerke</string>
|
||||
<string name="markets_common_my_portfolio">Mein Portfolio</string>
|
||||
<string name="markets_common_title">Markt</string>
|
||||
|
|
@ -448,6 +449,9 @@
|
|||
<string name="markets_sort_by_top_gainers_title">Top-Gewinner</string>
|
||||
<string name="markets_sort_by_top_losers_title">Top-Verlierer</string>
|
||||
<string name="markets_sort_by_trending_title">Beliebt</string>
|
||||
<string name="markets_staking_banner_description_placeholder">Staking ist der einfachste Weg, um Belohnungen für Deine Kryptowährung zu erhalten. %s</string>
|
||||
<string name="markets_staking_banner_description_show_more">Mehr anzeigen</string>
|
||||
<string name="markets_staking_banner_title">Verdiene bis zu %s APY</string>
|
||||
<string name="markets_token_details_about_token_title">Über %s</string>
|
||||
<plurals name="markets_token_details_amount_exchanges">
|
||||
<item quantity="one">%d börse</item>
|
||||
|
|
@ -530,6 +534,13 @@
|
|||
<string name="nft_details_base_information">Basisinformationen</string>
|
||||
<string name="nft_details_chain">Netzwerk</string>
|
||||
<string name="nft_details_contract_address">Vertragsadresse</string>
|
||||
<string name="nft_details_info_chain">Kontrollabschnitt</string>
|
||||
<string name="nft_details_info_contract_address">Kontrollabschnitt</string>
|
||||
<string name="nft_details_info_rarity_label">Kontrollabschnitt</string>
|
||||
<string name="nft_details_info_rarity_rank">Kontrollabschnitt</string>
|
||||
<string name="nft_details_info_token_address">Kontrollabschnitt</string>
|
||||
<string name="nft_details_info_token_id">Kontrollabschnitt</string>
|
||||
<string name="nft_details_info_token_standard">Kontrollabschnitt</string>
|
||||
<string name="nft_details_last_sale_price">Letzter Verkaufspreis</string>
|
||||
<string name="nft_details_rarity_label">Raritätsetikett</string>
|
||||
<string name="nft_details_rarity_rank">Seltenheitsgrad</string>
|
||||
|
|
@ -1051,6 +1062,8 @@
|
|||
<string name="transaction_history_transaction_validator">Validierer: %s</string>
|
||||
<string name="transfer_min_amount_error">Minimum %s</string>
|
||||
<string name="transfer_notification_invalid_minimum_transaction_amount_text">Der Mindesttransaktionsbetrag beträgt %1$s.</string>
|
||||
<string name="tron_will_be_send_token_fee_description">Die Netzwerkgebühren für beliebte Token im Tron-Netzwerk können höher sein. Das Staking von TRX kann helfen, die Transaktionskosten zu senken.</string>
|
||||
<string name="tron_will_be_send_token_fee_title">Spare bei den Tron-Netzwerkgebühren</string>
|
||||
<string name="try_to_load_data_again_button_title">Versuche es erneut</string>
|
||||
<string name="twin_error_same_card">Du hast dieselbe Karte oder Ring gescannt. Um ein Zwillings-Wallet zu erstellen, musst du die Karte oder Ring mit der Nummer %d scannen.</string>
|
||||
<string name="twin_error_wrong_twin">Du hast die falsche Doppelkarte oder Ring gescannt. Bitte versuche eine andere Karte oder Ring</string>
|
||||
|
|
@ -1237,6 +1250,7 @@
|
|||
<string name="wc_alert_connection_timeout_description">Zeitüberschreitungsfehler. Bitte versuche es später erneut.</string>
|
||||
<string name="wc_alert_connection_timeout_title">WalletConnect konnte nicht hergestellt werden</string>
|
||||
<string name="wc_alert_domain_issues_description">Diese Domäne kann nicht verifiziert werden. Überprüfe die Anfrage sorgfältig und bestätige diese dann.</string>
|
||||
<string name="wc_alert_session_disconnected_description">Geh zurück zu Deinem Browser und stell erneut eine Verbindung über WalletConnect her.</string>
|
||||
<string name="wc_alert_session_disconnected_title">WalletConnect-Sitzung wurde getrennt</string>
|
||||
<string name="wc_alert_unknown_error_description">Fehlercode: %s. Wenn das Problem weiterhin besteht, wende Dich bitte an unseren Support.</string>
|
||||
<string name="wc_alert_unknown_error_title">Wir haben einen unbekannten Fehler festgestellt.</string>
|
||||
|
|
@ -1244,14 +1258,22 @@
|
|||
<string name="wc_alert_unsupported_networks_title">Nicht unterstützte Netzwerke</string>
|
||||
<string name="wc_alert_verified_domain_description">Tangem unterstützt ein erforderliches Netzwerk um %s.</string>
|
||||
<string name="wc_alert_verified_domain_title">Verifizierte Domain</string>
|
||||
<string name="wc_alert_wrong_card_description">Falsche Karte oder falscher Ring in der Tangem-App ausgewählt</string>
|
||||
<string name="wc_alert_wrong_card_title">Wir haben eine Art Problem</string>
|
||||
<string name="wc_common_connect">Verbinden</string>
|
||||
<string name="wc_common_network">Netzwerk</string>
|
||||
<string name="wc_common_networks">Netzwerke</string>
|
||||
<string name="wc_common_wallet">Wallet</string>
|
||||
<string name="wc_connected_networks">Verbundene Netzwerke</string>
|
||||
<string name="wc_connection_reqeust_can_view_balance">Anzeige des Kontostands und der Aktivitäten in Deiner Wallet</string>
|
||||
<string name="wc_connection_reqeust_cant_sign">Signiere die Transaktionen ohne eine Vorankündigung</string>
|
||||
<string name="wc_connection_reqeust_request_approval">Genehmigung für Transaktionen anfordern</string>
|
||||
<string name="wc_connection_reqeust_will_not">Wird nicht in der Lage sein,</string>
|
||||
<string name="wc_connection_reqeust_would_like">Möchte</string>
|
||||
<string name="wc_connection_request">Verbindungsanfrage</string>
|
||||
<string name="wc_connections">Verbindungen</string>
|
||||
<string name="wc_contents">Inhalt</string>
|
||||
<string name="wc_copy_data_button_text">Daten kopieren</string>
|
||||
<string name="wc_disconnect_all">Alle trennen</string>
|
||||
<string name="wc_disconnect_all_alert_desc">Text über die Trennung aller dApps</string>
|
||||
<string name="wc_disconnect_all_alert_title">Alle dApps trennen</string>
|
||||
|
|
@ -1262,6 +1284,11 @@
|
|||
<string name="wc_no_sessions_title">Keine Sitzungen</string>
|
||||
<string name="wc_notification_security_risk_subtitle">Diese Domain wird von mehreren Sicherheitsanbietern als unsicher eingestuft. Verlasse diese umgehend, um Dein Vermögen zu schützen.</string>
|
||||
<string name="wc_notification_security_risk_title">Bekanntes Sicherheitsrisiko</string>
|
||||
<string name="wc_request_from">Anfrage von</string>
|
||||
<string name="wc_signature_type">Art der Signatur</string>
|
||||
<string name="wc_transaction_request">Transaktionsanfrage</string>
|
||||
<string name="wc_transaction_request_title">Transaktionsanfrage</string>
|
||||
<string name="wc_wallet_connect">Wallet verbinden</string>
|
||||
<string name="welcome_interrupted_backup_alert_discard">Verwerfen</string>
|
||||
<string name="welcome_interrupted_backup_alert_message">Du hast eine unterbrochene Sicherung. Möchtest du diese fortsetzen?</string>
|
||||
<string name="welcome_interrupted_backup_alert_resume">Ja, fortsetzen</string>
|
||||
|
|
|
|||
|
|
@ -527,6 +527,13 @@
|
|||
<string name="nft_details_base_information">基本情報</string>
|
||||
<string name="nft_details_chain">チェーン</string>
|
||||
<string name="nft_details_contract_address">コントラクトアドレス</string>
|
||||
<string name="nft_details_info_chain">スタブ</string>
|
||||
<string name="nft_details_info_contract_address">スタブ</string>
|
||||
<string name="nft_details_info_rarity_label">スタブ</string>
|
||||
<string name="nft_details_info_rarity_rank">スタブ</string>
|
||||
<string name="nft_details_info_token_address">スタブ</string>
|
||||
<string name="nft_details_info_token_id">スタブ</string>
|
||||
<string name="nft_details_info_token_standard">スタブ</string>
|
||||
<string name="nft_details_last_sale_price">最終販売価格</string>
|
||||
<string name="nft_details_rarity_label">レアリティ・ラベル</string>
|
||||
<string name="nft_details_rarity_rank">レアリティ・ランク</string>
|
||||
|
|
@ -1044,7 +1051,7 @@
|
|||
<string name="transaction_history_transaction_validator">バリデーター: %s</string>
|
||||
<string name="transfer_min_amount_error">最小%s</string>
|
||||
<string name="transfer_notification_invalid_minimum_transaction_amount_text">最小取引金額は%1$sです。</string>
|
||||
<string name="tron_will_be_send_token_fee_description">Tronネットワークの人気トークンの手数料は高めです。TRXをステーキングすると、より安く、あるいは無料で取引できます。</string>
|
||||
<string name="tron_will_be_send_token_fee_description">Tronネットワークの人気トークンの手数料は高い可能性があります。TRXをステーキングすると、取引コストを削減できる可能性があります。</string>
|
||||
<string name="tron_will_be_send_token_fee_title">Tronネットワーク手数料を節約</string>
|
||||
<string name="try_to_load_data_again_button_title">もう一度やり直してください</string>
|
||||
<string name="twin_error_same_card">同じカードをスキャンしました。ツインウォレットを作成するには、番号%dのカードをスキャンする必要があります。</string>
|
||||
|
|
@ -1237,6 +1244,7 @@
|
|||
<string name="wc_alert_verified_domain_title">検証済みドメイン</string>
|
||||
<string name="wc_alert_wrong_card_description">Tangemアプリで誤ったカードまたはリングが選択されました</string>
|
||||
<string name="wc_alert_wrong_card_title">問題が起きています</string>
|
||||
<string name="wc_common_address">アドレス</string>
|
||||
<string name="wc_common_connect">接続する</string>
|
||||
<string name="wc_common_network">ネットワーク</string>
|
||||
<string name="wc_common_networks">ネットワーク</string>
|
||||
|
|
@ -1249,6 +1257,8 @@
|
|||
<string name="wc_connection_reqeust_would_like">したい</string>
|
||||
<string name="wc_connection_request">接続リクエスト</string>
|
||||
<string name="wc_connections">接続</string>
|
||||
<string name="wc_contents">内容</string>
|
||||
<string name="wc_copy_data_button_text">データをコピー</string>
|
||||
<string name="wc_disconnect_all">すべての接続を解除する</string>
|
||||
<string name="wc_disconnect_all_alert_desc">すべてのdAppsの接続解除に関するテキスト</string>
|
||||
<string name="wc_disconnect_all_alert_title">すべてのdAppを接続解除する</string>
|
||||
|
|
@ -1259,6 +1269,11 @@
|
|||
<string name="wc_no_sessions_title">セッションなし</string>
|
||||
<string name="wc_notification_security_risk_subtitle">このドメインは複数のセキュリティプロバイダーから安全でないとの警告を受けています。あなたの資産を守るため、直ちにアクセスを中止してください。</string>
|
||||
<string name="wc_notification_security_risk_title">既知のセキュリティリスク</string>
|
||||
<string name="wc_request_from">リクエスト元</string>
|
||||
<string name="wc_signature_type">署名タイプ</string>
|
||||
<string name="wc_transaction_info_to_title">宛先</string>
|
||||
<string name="wc_transaction_request">取引リクエスト</string>
|
||||
<string name="wc_transaction_request_title">取引リクエスト</string>
|
||||
<string name="wc_wallet_connect">ウォレットコネクト</string>
|
||||
<string name="welcome_interrupted_backup_alert_discard">破棄</string>
|
||||
<string name="welcome_interrupted_backup_alert_message">バックアップが中断されました。再開しますか?</string>
|
||||
|
|
|
|||
|
|
@ -1305,6 +1305,7 @@
|
|||
<string name="wc_alert_verified_domain_title">Verified domain</string>
|
||||
<string name="wc_alert_wrong_card_description">Wrong card or ring selected in Tangem App</string>
|
||||
<string name="wc_alert_wrong_card_title">We\'ve got some kind of problem</string>
|
||||
<string name="wc_common_address">Address</string>
|
||||
<string name="wc_common_connect">Connect</string>
|
||||
<string name="wc_common_network">Network</string>
|
||||
<string name="wc_common_networks">Networks</string>
|
||||
|
|
@ -1331,6 +1332,7 @@
|
|||
<string name="wc_notification_security_risk_title">Known security risk</string>
|
||||
<string name="wc_request_from">Request from</string>
|
||||
<string name="wc_signature_type">Signature Type</string>
|
||||
<string name="wc_transaction_info_to_title">To</string>
|
||||
<string name="wc_transaction_request">Transaction request</string>
|
||||
<string name="wc_transaction_request_title">Transaction request</string>
|
||||
<string name="wc_wallet_connect">Wallet connect</string>
|
||||
|
|
|
|||
21
core/ui/src/main/res/drawable/ic_fee_new_24.xml
Normal file
21
core/ui/src/main/res/drawable/ic_fee_new_24.xml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="18dp"
|
||||
android:height="18dp"
|
||||
android:viewportWidth="18"
|
||||
android:viewportHeight="18">
|
||||
<path
|
||||
android:pathData="M9,0.547C8.407,0.547 7.867,0.701 7.283,0.956C6.721,1.201 6.073,1.562 5.271,2.008L2.073,3.788C1.611,4.045 1.214,4.374 0.939,4.825C0.662,5.278 0.547,5.793 0.547,6.357L0.547,6.411C0.546,6.602 0.546,6.825 0.6,7.027C0.733,7.53 1.055,7.86 1.448,8.035C1.663,8.13 1.887,8.175 2.088,8.194V13.66C1.167,14.188 0.547,15.181 0.547,16.318C0.547,16.945 1.055,17.453 1.682,17.453H8.23C8.644,17.453 8.98,17.117 8.98,16.703C8.98,16.289 8.644,15.953 8.23,15.953H2.09C2.254,15.267 2.872,14.757 3.608,14.757H8.23C8.644,14.757 8.98,14.421 8.98,14.007C8.98,13.593 8.644,13.257 8.23,13.257H6.669V8.21H15.572C15.834,8.21 16.205,8.19 16.553,8.035C16.946,7.86 17.268,7.53 17.401,7.027C17.455,6.825 17.454,6.602 17.454,6.411L17.454,6.357C17.454,5.793 17.339,5.278 17.062,4.825C16.787,4.374 16.39,4.045 15.928,3.788L12.73,2.008C11.928,1.562 11.28,1.201 10.718,0.956C10.134,0.701 9.594,0.547 9,0.547ZM5.968,3.337C6.81,2.868 7.395,2.543 7.883,2.33C8.356,2.124 8.685,2.047 9,2.047C9.316,2.047 9.645,2.124 10.118,2.33C10.606,2.543 11.191,2.868 12.033,3.337L15.198,5.098C15.506,5.269 15.679,5.437 15.782,5.606C15.883,5.772 15.954,6 15.954,6.357C15.954,6.489 15.954,6.563 15.951,6.617C15.95,6.635 15.95,6.646 15.949,6.652C15.948,6.657 15.946,6.66 15.945,6.663L15.942,6.664C15.923,6.673 15.884,6.686 15.817,6.695C15.75,6.705 15.67,6.71 15.572,6.71H2.429C2.331,6.71 2.251,6.705 2.184,6.695C2.116,6.686 2.078,6.673 2.059,6.664L2.056,6.663C2.055,6.66 2.053,6.657 2.052,6.652C2.051,6.646 2.051,6.635 2.05,6.617C2.047,6.563 2.047,6.489 2.047,6.357C2.047,6 2.118,5.772 2.219,5.606C2.322,5.437 2.495,5.269 2.802,5.098L5.968,3.337ZM3.608,13.257L3.588,13.257V8.21H5.169V13.257H3.608Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M10.396,15.788C10.103,16.081 10.103,16.556 10.396,16.849C10.689,17.142 11.164,17.142 11.457,16.849L16.849,11.456C17.142,11.163 17.142,10.689 16.849,10.396C16.556,10.103 16.081,10.103 15.788,10.396L10.396,15.788Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M10.176,11.503C10.176,10.77 10.77,10.176 11.504,10.176C12.237,10.176 12.832,10.77 12.832,11.503C12.832,12.237 12.237,12.831 11.504,12.831C10.77,12.831 10.176,12.237 10.176,11.503ZM11.504,11.676C11.599,11.676 11.676,11.599 11.676,11.503C11.676,11.408 11.599,11.331 11.504,11.331C11.409,11.331 11.332,11.408 11.332,11.503C11.332,11.599 11.409,11.676 11.504,11.676Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M15.741,14.412C15.008,14.412 14.413,15.007 14.413,15.74C14.413,16.473 15.008,17.068 15.741,17.068C16.474,17.068 17.069,16.473 17.069,15.74C17.069,15.007 16.474,14.412 15.741,14.412ZM15.913,15.74C15.913,15.835 15.836,15.912 15.741,15.912C15.646,15.912 15.569,15.835 15.569,15.74C15.569,15.645 15.646,15.568 15.741,15.568C15.836,15.568 15.913,15.645 15.913,15.74Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
17
core/ui/src/main/res/drawable/ic_user_square_24.xml
Normal file
17
core/ui/src/main/res/drawable/ic_user_square_24.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:pathData="M9.992,4.701C8.321,4.701 6.964,6.054 6.964,7.726C6.964,9.397 8.321,10.75 9.992,10.75C11.663,10.75 13.02,9.397 13.02,7.726C13.02,6.054 11.663,4.701 9.992,4.701ZM8.464,7.726C8.464,6.885 9.147,6.201 9.992,6.201C10.837,6.201 11.52,6.885 11.52,7.726C11.52,8.567 10.837,9.25 9.992,9.25C9.147,9.25 8.464,8.567 8.464,7.726Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M6.448,15.067C8.288,13.14 11.709,13.068 13.542,15.058C13.823,15.362 14.298,15.382 14.602,15.101C14.907,14.82 14.926,14.346 14.645,14.041C12.191,11.377 7.766,11.515 5.363,14.031C5.077,14.331 5.088,14.806 5.387,15.092C5.687,15.378 6.162,15.367 6.448,15.067Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M10.056,0.606H9.942C7.953,0.606 6.384,0.606 5.157,0.771C3.897,0.941 2.886,1.296 2.091,2.092C1.295,2.887 0.94,3.898 0.77,5.158C0.605,6.385 0.605,7.954 0.605,9.943V10.057C0.605,12.046 0.605,13.615 0.77,14.842C0.94,16.102 1.295,17.113 2.091,17.908C2.886,18.704 3.897,19.059 5.157,19.229C6.384,19.394 7.953,19.394 9.942,19.394H10.056C12.045,19.394 13.614,19.394 14.841,19.229C16.101,19.059 17.112,18.704 17.907,17.908C18.703,17.113 19.058,16.102 19.228,14.842C19.393,13.615 19.393,12.046 19.393,10.057V9.943C19.393,7.954 19.393,6.385 19.228,5.158C19.058,3.898 18.703,2.887 17.907,2.092C17.112,1.296 16.101,0.941 14.841,0.771C13.614,0.606 12.045,0.606 10.056,0.606ZM3.152,3.153C3.622,2.682 4.263,2.405 5.357,2.258C6.472,2.108 7.941,2.106 9.999,2.106C12.057,2.106 13.526,2.108 14.641,2.258C15.735,2.405 16.376,2.682 16.846,3.153C17.317,3.623 17.594,4.264 17.741,5.358C17.891,6.473 17.893,7.941 17.893,10C17.893,12.059 17.891,13.527 17.741,14.642C17.594,15.736 17.317,16.377 16.846,16.847C16.376,17.318 15.735,17.595 14.641,17.742C13.526,17.892 12.057,17.894 9.999,17.894C7.941,17.894 6.472,17.892 5.357,17.742C4.263,17.595 3.622,17.318 3.152,16.847C2.681,16.377 2.404,15.736 2.257,14.642C2.107,13.527 2.105,12.059 2.105,10C2.105,7.941 2.107,6.473 2.257,5.358C2.404,4.264 2.681,3.623 3.152,3.153Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
|
|
@ -42,6 +42,7 @@ import javax.inject.Singleton
|
|||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@Suppress("TooManyFunctions")
|
||||
internal object WalletConnectDataModule {
|
||||
|
||||
@Provides
|
||||
|
|
@ -86,6 +87,7 @@ internal object WalletConnectDataModule {
|
|||
dispatchers: CoroutineDispatcherProvider,
|
||||
legacyStore: WalletConnectSessionsRepository,
|
||||
getWallets: GetWalletsUseCase,
|
||||
associateNetworks: AssociateNetworksDelegate,
|
||||
): DefaultWcSessionsManager {
|
||||
val scope = CoroutineScope(SupervisorJob() + dispatchers.io)
|
||||
return DefaultWcSessionsManager(
|
||||
|
|
@ -93,6 +95,7 @@ internal object WalletConnectDataModule {
|
|||
dispatchers = dispatchers,
|
||||
legacyStore = legacyStore,
|
||||
getWallets = getWallets,
|
||||
associateNetworks = associateNetworks,
|
||||
scope = scope,
|
||||
)
|
||||
}
|
||||
|
|
@ -121,12 +124,12 @@ internal object WalletConnectDataModule {
|
|||
@Singleton
|
||||
fun wcEthNetwork(
|
||||
@SdkMoshi moshi: Moshi,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
sessionsManager: WcSessionsManager,
|
||||
factories: WcEthNetwork.Factories,
|
||||
namespaceConverter: WcEthNetwork.NamespaceConverter,
|
||||
): WcEthNetwork = WcEthNetwork(
|
||||
moshi = moshi,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
namespaceConverter = namespaceConverter,
|
||||
sessionsManager = sessionsManager,
|
||||
factories = factories,
|
||||
)
|
||||
|
|
@ -135,7 +138,7 @@ internal object WalletConnectDataModule {
|
|||
@Singleton
|
||||
fun wcSolanaNetwork(
|
||||
@SdkMoshi moshi: Moshi,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
namespaceConverter: WcSolanaNetwork.NamespaceConverter,
|
||||
sessionsManager: WcSessionsManager,
|
||||
factories: WcSolanaNetwork.Factories,
|
||||
walletManager: UserWalletManager,
|
||||
|
|
@ -143,28 +146,28 @@ internal object WalletConnectDataModule {
|
|||
moshi = moshi,
|
||||
sessionsManager = sessionsManager,
|
||||
factories = factories,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
namespaceConverter = namespaceConverter,
|
||||
walletManager = walletManager,
|
||||
)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun caipNamespaceDelegate(
|
||||
diHelperBox: DiHelperBox,
|
||||
namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
): CaipNamespaceDelegate = CaipNamespaceDelegate(
|
||||
namespaceConverters = diHelperBox.converters,
|
||||
namespaceConverters = namespaceConverters,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun associateNetworksDelegate(
|
||||
diHelperBox: DiHelperBox,
|
||||
namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>,
|
||||
getWallets: GetWalletsUseCase,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
): AssociateNetworksDelegate = AssociateNetworksDelegate(
|
||||
namespaceConverters = diHelperBox.converters,
|
||||
namespaceConverters = namespaceConverters,
|
||||
getWallets = getWallets,
|
||||
currenciesRepository = currenciesRepository,
|
||||
)
|
||||
|
|
@ -176,10 +179,16 @@ internal object WalletConnectDataModule {
|
|||
ethNetwork,
|
||||
solanaNetwork,
|
||||
),
|
||||
converters = setOf(
|
||||
ethNetwork,
|
||||
solanaNetwork,
|
||||
),
|
||||
)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun namespaceConverters(
|
||||
ethNamespaceConverter: WcEthNetwork.NamespaceConverter,
|
||||
solanaNamespaceConverter: WcSolanaNetwork.NamespaceConverter,
|
||||
): Set<@JvmSuppressWildcards WcNamespaceConverter> = setOf(
|
||||
ethNamespaceConverter,
|
||||
solanaNamespaceConverter,
|
||||
)
|
||||
|
||||
@Provides
|
||||
|
|
@ -188,6 +197,20 @@ internal object WalletConnectDataModule {
|
|||
return DefaultWcRequestUseCaseFactory(diHelperBox.handlers)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun wcEthNetworkNamespaceConverter(excludedBlockchains: ExcludedBlockchains): WcEthNetwork.NamespaceConverter {
|
||||
return WcEthNetwork.NamespaceConverter(excludedBlockchains)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun wcSolanaNetworkNamespaceConverter(
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
): WcSolanaNetwork.NamespaceConverter {
|
||||
return WcSolanaNetwork.NamespaceConverter(excludedBlockchains)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesWcDisconnectUseCase(sessionsManager: WcSessionsManager): WcDisconnectUseCase {
|
||||
|
|
@ -195,7 +218,6 @@ internal object WalletConnectDataModule {
|
|||
}
|
||||
|
||||
internal class DiHelperBox(
|
||||
val converters: Set<WcNamespaceConverter>,
|
||||
val handlers: Set<WcRequestToUseCaseConverter>,
|
||||
)
|
||||
}
|
||||
|
|
@ -22,12 +22,10 @@ import jakarta.inject.Inject
|
|||
|
||||
internal class WcEthNetwork(
|
||||
private val moshi: Moshi,
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
private val sessionsManager: WcSessionsManager,
|
||||
private val factories: Factories,
|
||||
) : WcRequestToUseCaseConverter, WcNamespaceConverter {
|
||||
|
||||
override val namespaceKey: NamespaceKey = NamespaceKey("eip155")
|
||||
private val namespaceConverter: NamespaceConverter,
|
||||
) : WcRequestToUseCaseConverter {
|
||||
|
||||
override fun toWcMethodName(request: WcSdkSessionRequest): WcEthMethodName? {
|
||||
val methodKey = request.request.method
|
||||
|
|
@ -39,7 +37,7 @@ internal class WcEthNetwork(
|
|||
val name = toWcMethodName(request) ?: return null
|
||||
val method: WcEthMethod = name.toMethod(request) ?: return null
|
||||
val session = sessionsManager.findSessionByTopic(request.topic) ?: return null
|
||||
val network = toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null
|
||||
val network = namespaceConverter.toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null
|
||||
val accountAddress = when (method) {
|
||||
is WcEthMethod.MessageSign -> method.account
|
||||
is WcEthMethod.SendTransaction -> method.transaction.from
|
||||
|
|
@ -100,24 +98,31 @@ internal class WcEthNetwork(
|
|||
return WcEthMethod.SignTypedData(params = params, account = account, dataForSign = data)
|
||||
}
|
||||
|
||||
override fun toNetwork(chainId: String, wallet: UserWallet): Network? {
|
||||
return toNetwork(chainId, wallet, excludedBlockchains)
|
||||
}
|
||||
internal class NamespaceConverter constructor(
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
) : WcNamespaceConverter {
|
||||
|
||||
override fun toBlockchain(chainId: CAIP2): Blockchain? {
|
||||
if (chainId.namespace != namespaceKey.key) return null
|
||||
val ethChainId = chainId.reference.toIntOrNull() ?: return null
|
||||
return Blockchain.fromChainId(ethChainId)
|
||||
}
|
||||
override val namespaceKey: NamespaceKey = NamespaceKey("eip155")
|
||||
|
||||
override fun toCAIP2(network: Network): CAIP2? {
|
||||
val blockchain = Blockchain.fromId(network.id.value)
|
||||
if (!blockchain.isEvm()) return null
|
||||
val chainId = blockchain.getChainId() ?: return null
|
||||
return CAIP2(
|
||||
namespace = namespaceKey.key,
|
||||
reference = chainId.toString(),
|
||||
)
|
||||
override fun toNetwork(chainId: String, wallet: UserWallet): Network? {
|
||||
return toNetwork(chainId, wallet, excludedBlockchains)
|
||||
}
|
||||
|
||||
override fun toBlockchain(chainId: CAIP2): Blockchain? {
|
||||
if (chainId.namespace != namespaceKey.key) return null
|
||||
val ethChainId = chainId.reference.toIntOrNull() ?: return null
|
||||
return Blockchain.fromChainId(ethChainId)
|
||||
}
|
||||
|
||||
override fun toCAIP2(network: Network): CAIP2? {
|
||||
val blockchain = Blockchain.fromId(network.id.value)
|
||||
if (!blockchain.isEvm()) return null
|
||||
val chainId = blockchain.getChainId() ?: return null
|
||||
return CAIP2(
|
||||
namespace = namespaceKey.key,
|
||||
reference = chainId.toString(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class Factories @Inject constructor(
|
||||
|
|
|
|||
|
|
@ -26,11 +26,9 @@ internal class WcSolanaNetwork(
|
|||
private val moshi: Moshi,
|
||||
private val sessionsManager: WcSessionsManager,
|
||||
private val factories: Factories,
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
private val namespaceConverter: NamespaceConverter,
|
||||
private val walletManager: UserWalletManager,
|
||||
) : WcNamespaceConverter, WcRequestToUseCaseConverter {
|
||||
|
||||
override val namespaceKey: NamespaceKey = NamespaceKey("solana")
|
||||
) : WcRequestToUseCaseConverter {
|
||||
|
||||
override fun toWcMethodName(request: WcSdkSessionRequest): WcSolanaMethodName? {
|
||||
val methodKey = request.request.method
|
||||
|
|
@ -42,7 +40,7 @@ internal class WcSolanaNetwork(
|
|||
val name = toWcMethodName(request) ?: return null
|
||||
val method: WcSolanaMethod = name.toMethod(request) ?: return null
|
||||
val session = sessionsManager.findSessionByTopic(request.topic) ?: return null
|
||||
val network = toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null
|
||||
val network = namespaceConverter.toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null
|
||||
val accountAddress = getAccountAddress(network)
|
||||
val context = WcMethodUseCaseContext(
|
||||
session = session,
|
||||
|
|
@ -66,31 +64,38 @@ internal class WcSolanaNetwork(
|
|||
}
|
||||
}
|
||||
|
||||
override fun toBlockchain(chainId: CAIP2): Blockchain? {
|
||||
if (chainId.namespace != namespaceKey.key) return null
|
||||
return when (chainId.reference) {
|
||||
MAINNET_CHAIN_ID -> Blockchain.Solana
|
||||
TESTNET_CHAIN_ID -> Blockchain.SolanaTestnet
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
internal class NamespaceConverter @Inject constructor(
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
) : WcNamespaceConverter {
|
||||
|
||||
override fun toNetwork(chainId: String, wallet: UserWallet): Network? {
|
||||
return toNetwork(chainId, wallet, excludedBlockchains)
|
||||
}
|
||||
override val namespaceKey: NamespaceKey = NamespaceKey("solana")
|
||||
|
||||
override fun toCAIP2(network: Network): CAIP2? {
|
||||
val blockchain = Blockchain.fromId(network.id.value)
|
||||
val chainId = when (blockchain) {
|
||||
Blockchain.Solana -> MAINNET_CHAIN_ID
|
||||
Blockchain.SolanaTestnet -> TESTNET_CHAIN_ID
|
||||
else -> null
|
||||
override fun toBlockchain(chainId: CAIP2): Blockchain? {
|
||||
if (chainId.namespace != namespaceKey.key) return null
|
||||
return when (chainId.reference) {
|
||||
MAINNET_CHAIN_ID -> Blockchain.Solana
|
||||
TESTNET_CHAIN_ID -> Blockchain.SolanaTestnet
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun toNetwork(chainId: String, wallet: UserWallet): Network? {
|
||||
return toNetwork(chainId, wallet, excludedBlockchains)
|
||||
}
|
||||
|
||||
override fun toCAIP2(network: Network): CAIP2? {
|
||||
val blockchain = Blockchain.fromId(network.id.value)
|
||||
val chainId = when (blockchain) {
|
||||
Blockchain.Solana -> MAINNET_CHAIN_ID
|
||||
Blockchain.SolanaTestnet -> TESTNET_CHAIN_ID
|
||||
else -> null
|
||||
}
|
||||
chainId ?: return null
|
||||
return CAIP2(
|
||||
namespace = namespaceKey.key,
|
||||
reference = chainId,
|
||||
)
|
||||
}
|
||||
chainId ?: return null
|
||||
return CAIP2(
|
||||
namespace = namespaceKey.key,
|
||||
reference = chainId,
|
||||
)
|
||||
}
|
||||
|
||||
private fun WcSolanaMethodName.toMethod(request: WcSdkSessionRequest): WcSolanaMethod? {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.data.walletconnect.pair
|
||||
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.reown.walletkit.client.Wallet.Model.Namespace
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
|
|
@ -16,6 +17,16 @@ internal class AssociateNetworksDelegate constructor(
|
|||
private val currenciesRepository: CurrenciesRepository,
|
||||
) {
|
||||
|
||||
suspend fun associate(wallet: UserWallet, namespaces: Map<String, Namespace.Session>): Set<Network> {
|
||||
val walletNetworks = getWalletNetworks(wallet)
|
||||
val namespacesSet = namespaces.values.flatMap { proposal -> proposal.chains ?: listOf() }.toSet()
|
||||
return namespacesSet.mapNotNullTo(mutableSetOf()) { chainId ->
|
||||
val wcNetwork = namespaceConverters
|
||||
.firstNotNullOfOrNull { it.toNetwork(chainId, wallet) } ?: return@mapNotNullTo null
|
||||
walletNetworks.find { network -> wcNetwork.id == network.id }
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(WcPairError.UnsupportedNetworks::class)
|
||||
suspend fun associate(sessionProposal: Wallet.Model.SessionProposal): Map<UserWallet, ProposalNetwork> {
|
||||
val userWallets = getWallets.invokeSync().filter { it.isMultiCurrency }
|
||||
|
|
@ -31,9 +42,7 @@ internal class AssociateNetworksDelegate constructor(
|
|||
requiredNamespaces: Set<String>,
|
||||
optionalNamespaces: Set<String>,
|
||||
): ProposalNetwork {
|
||||
val walletNetworks = currenciesRepository.getMultiCurrencyWalletCurrenciesSync(wallet.walletId)
|
||||
.filterIsInstance<CryptoCurrency.Coin>()
|
||||
.map { it.network }
|
||||
val walletNetworks = getWalletNetworks(wallet)
|
||||
|
||||
val unknownRequired = mutableSetOf<String>()
|
||||
val missingRequired = mutableSetOf<Network>()
|
||||
|
|
@ -74,6 +83,11 @@ internal class AssociateNetworksDelegate constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun getWalletNetworks(wallet: UserWallet): List<Network> =
|
||||
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(wallet.walletId)
|
||||
.filterIsInstance<CryptoCurrency.Coin>()
|
||||
.map { it.network }
|
||||
|
||||
private fun Map<String, Wallet.Model.Namespace.Proposal>.setOfChainId(): Set<String> =
|
||||
this.values.flatMap { proposal -> proposal.chains ?: listOf() }.toSet()
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import com.tangem.domain.walletconnect.model.sdkcopy.WcAppMetaData
|
|||
import com.tangem.domain.walletconnect.repository.WcSessionsManager
|
||||
import com.tangem.domain.walletconnect.usecase.pair.WcPairState
|
||||
import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -78,9 +77,11 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
sessionForApprove = sessionForApprove,
|
||||
sdkSessionProposal = sdkSessionProposal,
|
||||
).map { settledSession ->
|
||||
val newSession = settledSession.session.toDomain(
|
||||
val newSession = WcSession(
|
||||
wallet = sessionForApprove.wallet,
|
||||
sdkModel = WcSdkSessionConverter.convert(settledSession.session),
|
||||
securityStatus = proposalState.dAppSession.securityStatus,
|
||||
networks = sessionForApprove.network.toSet(),
|
||||
)
|
||||
sessionsManager.saveSession(newSession)
|
||||
newSession
|
||||
|
|
@ -141,14 +142,6 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
}
|
||||
},)
|
||||
|
||||
private fun Wallet.Model.Session.toDomain(wallet: UserWallet, securityStatus: CheckDAppResult): WcSession {
|
||||
return WcSession(
|
||||
wallet = wallet,
|
||||
sdkModel = WcSdkSessionConverter.convert(this),
|
||||
securityStatus = securityStatus,
|
||||
)
|
||||
}
|
||||
|
||||
private sealed interface TerminalAction {
|
||||
data class Approve(val sessionForApprove: WcSessionApprove) : TerminalAction
|
||||
data object Reject : TerminalAction
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import arrow.core.right
|
|||
import com.domain.blockaid.models.dapp.CheckDAppResult
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.reown.walletkit.client.WalletKit
|
||||
import com.tangem.data.walletconnect.pair.AssociateNetworksDelegate
|
||||
import com.tangem.data.walletconnect.utils.WcSdkObserver
|
||||
import com.tangem.data.walletconnect.utils.WcSdkSessionConverter
|
||||
import com.tangem.datasource.local.walletconnect.WalletConnectStore
|
||||
|
|
@ -29,6 +30,7 @@ internal class DefaultWcSessionsManager(
|
|||
private val legacyStore: WalletConnectSessionsRepository,
|
||||
private val getWallets: GetWalletsUseCase,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val associateNetworks: AssociateNetworksDelegate,
|
||||
private val scope: CoroutineScope,
|
||||
) : WcSessionsManager, WcSdkObserver {
|
||||
|
||||
|
|
@ -76,10 +78,12 @@ internal class DefaultWcSessionsManager(
|
|||
?: return@withContext null
|
||||
val sdkSession = WalletKit.getActiveSessionByTopic(topic) ?: return@withContext null
|
||||
val wallet = storedSession.wallet
|
||||
val networks = associateNetworks.associate(wallet, sdkSession.namespaces)
|
||||
WcSession(
|
||||
wallet = wallet,
|
||||
sdkModel = WcSdkSessionConverter.convert(sdkSession),
|
||||
securityStatus = storedSession.securityStatus,
|
||||
networks = networks,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +118,7 @@ internal class DefaultWcSessionsManager(
|
|||
return mustSaveInNewStore.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun associate(
|
||||
private suspend fun associate(
|
||||
inSdk: List<Wallet.Model.Session>,
|
||||
inStore: Set<WcSessionDTO>,
|
||||
wallets: List<UserWallet>,
|
||||
|
|
@ -122,7 +126,13 @@ internal class DefaultWcSessionsManager(
|
|||
val wcSessions = inStore.mapNotNull { session ->
|
||||
val wallet = wallets.find { it.walletId == session.walletId } ?: return@mapNotNull null
|
||||
val sdkSession = inSdk.find { it.topic == session.topic } ?: return@mapNotNull null
|
||||
WcSession(wallet = wallet, sdkModel = WcSdkSessionConverter.convert(sdkSession), session.securityStatus)
|
||||
val networks = associateNetworks.associate(wallet, sdkSession.namespaces)
|
||||
WcSession(
|
||||
wallet = wallet,
|
||||
sdkModel = WcSdkSessionConverter.convert(sdkSession),
|
||||
securityStatus = session.securityStatus,
|
||||
networks = networks,
|
||||
)
|
||||
}
|
||||
return wcSessions
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import com.tangem.domain.walletconnect.model.WcSession
|
|||
import com.tangem.domain.walletconnect.model.WcSessionApprove
|
||||
import com.tangem.domain.walletconnect.repository.WcSessionsManager
|
||||
import com.tangem.domain.walletconnect.usecase.pair.WcPairState
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerifyOrder
|
||||
import io.mockk.mockk
|
||||
|
|
@ -91,6 +92,7 @@ internal class DefaultWcPairUseCaseTest {
|
|||
wallet = sessionForApprove.wallet,
|
||||
sdkModel = WcSdkSessionConverter.convert(this),
|
||||
securityStatus = CheckDAppResult.SAFE,
|
||||
networks = setOf(),
|
||||
)
|
||||
|
||||
private fun useCaseFactory() = DefaultWcPairUseCase(
|
||||
|
|
@ -99,7 +101,7 @@ internal class DefaultWcPairUseCaseTest {
|
|||
caipNamespaceDelegate = caipNamespaceDelegate,
|
||||
sdkDelegate = sdkDelegate,
|
||||
blockAidVerifier = blockAidVerifier,
|
||||
pairRequest = WcPairRequest(url, source),
|
||||
pairRequest = WcPairRequest(userWalletId = UserWalletId(""), uri = url, source = source),
|
||||
)
|
||||
|
||||
@Before
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import com.tangem.domain.tokens.TokensFeatureToggles
|
|||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
|
@ -24,7 +23,6 @@ class SaveManagedTokensUseCase(
|
|||
private val customTokensRepository: CustomTokensRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val derivationsRepository: DerivationsRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
|
|
@ -102,20 +100,12 @@ class SaveManagedTokensUseCase(
|
|||
val networkToUpdate = currenciesToAdd.map { it.network }
|
||||
.subtract(existingCurrencies.map { it.network }.toSet())
|
||||
|
||||
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
multiNetworkStatusFetcher(
|
||||
MultiNetworkStatusFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
networks = networksToUpdate + networkToUpdate,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
networksRepository.getNetworkStatusesSync(
|
||||
multiNetworkStatusFetcher(
|
||||
MultiNetworkStatusFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
networks = networksToUpdate + networkToUpdate,
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedYieldBalances(
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import com.tangem.domain.tokens.TokensFeatureToggles
|
|||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
|
|
@ -30,7 +29,6 @@ class SaveMarketTokensUseCase(
|
|||
private val derivationsRepository: DerivationsRepository,
|
||||
private val marketsTokenRepository: MarketsTokenRepository,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
|
|
@ -83,20 +81,12 @@ class SaveMarketTokensUseCase(
|
|||
}
|
||||
|
||||
private suspend fun refreshUpdatedNetworks(userWalletId: UserWalletId, addedCurrencies: List<CryptoCurrency>) {
|
||||
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
multiNetworkStatusFetcher(
|
||||
MultiNetworkStatusFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
networks = addedCurrencies.map(CryptoCurrency::network).toSet(),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
networksRepository.getNetworkStatusesSync(
|
||||
multiNetworkStatusFetcher(
|
||||
MultiNetworkStatusFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
networks = addedCurrencies.map(CryptoCurrency::network).toSet(),
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedYieldBalances(
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import com.tangem.common.card.EllipticCurve
|
|||
import com.tangem.common.card.EncryptionMode
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
|
||||
import com.tangem.common.card.FirmwareVersion as SdkFirmwareVersion
|
||||
import com.tangem.operations.attestation.Attestation
|
||||
import java.util.Date
|
||||
import com.tangem.common.card.FirmwareVersion as SdkFirmwareVersion
|
||||
|
||||
// TODO: Move to :domain:card:models
|
||||
/**
|
||||
|
|
@ -189,6 +189,8 @@ data class CardDTO(
|
|||
minor != other.minor -> minor.compareTo(other.minor)
|
||||
else -> patch.compareTo(other.patch)
|
||||
}
|
||||
|
||||
fun toSdkFirmwareVersion() = SdkFirmwareVersion(major = major, minor = minor)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
|
|||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.async
|
||||
|
|
@ -29,7 +28,6 @@ import kotlinx.coroutines.coroutineScope
|
|||
@Suppress("LongParameterList")
|
||||
class AddCryptoCurrenciesUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
|
|
@ -139,26 +137,13 @@ class AddCryptoCurrenciesUseCase(
|
|||
}
|
||||
?.network
|
||||
|
||||
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
multiNetworkStatusFetcher(
|
||||
MultiNetworkStatusFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
networks = setOfNotNull(networksToUpdate, networkToUpdate),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
catch(
|
||||
{
|
||||
networksRepository.getNetworkStatusesSync(
|
||||
userWalletId = userWalletId,
|
||||
networks = setOfNotNull(networksToUpdate, networkToUpdate),
|
||||
refresh = true,
|
||||
)
|
||||
},
|
||||
) {
|
||||
raise(it)
|
||||
}
|
||||
}
|
||||
multiNetworkStatusFetcher(
|
||||
MultiNetworkStatusFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
networks = setOfNotNull(networksToUpdate, networkToUpdate),
|
||||
),
|
||||
)
|
||||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedYieldBalances(userWalletId: UserWalletId, addedCurrency: CryptoCurrency) {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.tangem.domain.tokens.error.TokenListError
|
|||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.async
|
||||
|
|
@ -23,7 +22,6 @@ import kotlinx.coroutines.coroutineScope
|
|||
@Suppress("LongParameterList")
|
||||
class FetchCardTokenListUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
|
|
@ -41,7 +39,6 @@ class FetchCardTokenListUseCase(
|
|||
fetchNetworksStatuses(
|
||||
userWalletId = userWalletId,
|
||||
networks = currencies.mapTo(destination = hashSetOf(), transform = CryptoCurrency::network),
|
||||
refresh = refresh,
|
||||
)
|
||||
}
|
||||
val fetchQuotes = async {
|
||||
|
|
@ -80,19 +77,12 @@ class FetchCardTokenListUseCase(
|
|||
private suspend fun Raise<TokenListError>.fetchNetworksStatuses(
|
||||
userWalletId: UserWalletId,
|
||||
networks: Set<Network>,
|
||||
refresh: Boolean,
|
||||
) {
|
||||
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
multiNetworkStatusFetcher(
|
||||
MultiNetworkStatusFetcher.Params(userWalletId = userWalletId, networks = networks),
|
||||
)
|
||||
.mapLeft { TokenListError.DataError(it) }
|
||||
} else {
|
||||
catch(
|
||||
block = { networksRepository.getNetworkStatusesSync(userWalletId, networks, refresh) },
|
||||
catch = { raise(TokenListError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
multiNetworkStatusFetcher(
|
||||
MultiNetworkStatusFetcher.Params(userWalletId = userWalletId, networks = networks),
|
||||
)
|
||||
.mapLeft(TokenListError::DataError)
|
||||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun fetchQuotes(currenciesIds: Set<CryptoCurrency.RawID>, refresh: Boolean) {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.tangem.domain.tokens.error.CurrencyStatusError
|
|||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.async
|
||||
|
|
@ -26,14 +25,12 @@ import kotlinx.coroutines.coroutineScope
|
|||
* by providing a specific currency ID or fetching the status of the primary currency.
|
||||
*
|
||||
* @param currenciesRepository The repository for retrieving currency-related data.
|
||||
* @param networksRepository The repository for retrieving network-related data.
|
||||
* @param quotesRepository The repository for retrieving cryptocurrency quotes.
|
||||
*/
|
||||
// TODO: Add tests
|
||||
@Suppress("LongParameterList")
|
||||
class FetchCurrencyStatusUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
|
|
@ -86,7 +83,7 @@ class FetchCurrencyStatusUseCase(
|
|||
refresh: Boolean,
|
||||
) = coroutineScope {
|
||||
val fetchStatus = async {
|
||||
fetchNetworkStatus(userWalletId, currency.network, refresh)
|
||||
fetchNetworkStatus(userWalletId, currency.network)
|
||||
}
|
||||
val fetchQuote = async {
|
||||
fetchQuote(currency.id, refresh)
|
||||
|
|
@ -120,23 +117,12 @@ class FetchCurrencyStatusUseCase(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun Raise<CurrencyStatusError>.fetchNetworkStatus(
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
refresh: Boolean,
|
||||
) {
|
||||
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
singleNetworkStatusFetcher(
|
||||
params = SingleNetworkStatusFetcher.Params(userWalletId = userWalletId, network = network),
|
||||
)
|
||||
.mapLeft { CurrencyStatusError.DataError(it) }
|
||||
} else {
|
||||
catch(
|
||||
block = { networksRepository.getNetworkStatusesSync(userWalletId, setOf(network), refresh) },
|
||||
) {
|
||||
raise(CurrencyStatusError.DataError(it))
|
||||
}
|
||||
}
|
||||
private suspend fun Raise<CurrencyStatusError>.fetchNetworkStatus(userWalletId: UserWalletId, network: Network) {
|
||||
singleNetworkStatusFetcher(
|
||||
params = SingleNetworkStatusFetcher.Params(userWalletId = userWalletId, network = network),
|
||||
)
|
||||
.mapLeft { CurrencyStatusError.DataError(it) }
|
||||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun Raise<CurrencyStatusError>.fetchQuote(currencyId: CryptoCurrency.ID, refresh: Boolean) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import com.tangem.domain.tokens.error.TokenListError
|
|||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.async
|
||||
|
|
@ -27,7 +26,6 @@ import kotlinx.coroutines.coroutineScope
|
|||
* network statuses, and quotes for tokens associated with a user's wallet.
|
||||
*
|
||||
* @param currenciesRepository The repository for retrieving currency-related data.
|
||||
* @param networksRepository The repository for retrieving network-related data.
|
||||
* @param quotesRepository The repository for retrieving cryptocurrency quotes.
|
||||
* @param stakingRepository The repository for retrieving staking-related data.
|
||||
*/
|
||||
|
|
@ -35,7 +33,6 @@ import kotlinx.coroutines.coroutineScope
|
|||
@Suppress("LongParameterList")
|
||||
class FetchTokenListUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
|
|
@ -71,7 +68,6 @@ class FetchTokenListUseCase(
|
|||
fetchNetworksStatuses(
|
||||
userWalletId = userWalletId,
|
||||
networks = currencies.mapTo(hashSetOf()) { it.network },
|
||||
refresh = mode.refreshNetworksStatuses,
|
||||
)
|
||||
}
|
||||
val fetchQuotes = async {
|
||||
|
|
@ -111,23 +107,12 @@ class FetchTokenListUseCase(
|
|||
private suspend fun Raise<TokenListError>.fetchNetworksStatuses(
|
||||
userWalletId: UserWalletId,
|
||||
networks: Set<Network>,
|
||||
refresh: Boolean,
|
||||
) {
|
||||
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
if (refresh) {
|
||||
multiNetworkStatusFetcher(
|
||||
params = MultiNetworkStatusFetcher.Params(userWalletId, networks),
|
||||
)
|
||||
.mapLeft { TokenListError.DataError(it) }
|
||||
.bind()
|
||||
}
|
||||
} else {
|
||||
catch(
|
||||
block = { networksRepository.getNetworkStatusesSync(userWalletId, networks, refresh) },
|
||||
) {
|
||||
raise(TokenListError.DataError(it))
|
||||
}
|
||||
}
|
||||
multiNetworkStatusFetcher(
|
||||
params = MultiNetworkStatusFetcher.Params(userWalletId = userWalletId, networks = networks),
|
||||
)
|
||||
.mapLeft(TokenListError::DataError)
|
||||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun fetchQuotes(currenciesIds: Set<CryptoCurrency.ID>, refresh: Boolean) {
|
||||
|
|
@ -175,25 +160,21 @@ class FetchTokenListUseCase(
|
|||
*/
|
||||
enum class RefreshMode(
|
||||
internal val refreshCurrencies: Boolean,
|
||||
internal val refreshNetworksStatuses: Boolean,
|
||||
internal val refreshQuotes: Boolean,
|
||||
internal val refreshYieldBalances: Boolean,
|
||||
) {
|
||||
NONE(
|
||||
refreshCurrencies = false,
|
||||
refreshNetworksStatuses = false,
|
||||
refreshQuotes = false,
|
||||
refreshYieldBalances = false,
|
||||
),
|
||||
FULL(
|
||||
refreshCurrencies = true,
|
||||
refreshNetworksStatuses = true,
|
||||
refreshQuotes = true,
|
||||
refreshYieldBalances = true,
|
||||
),
|
||||
SKIP_CURRENCIES(
|
||||
refreshCurrencies = false,
|
||||
refreshNetworksStatuses = true,
|
||||
refreshQuotes = true,
|
||||
refreshYieldBalances = true,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.error.mapper.mapToCurrencyError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
class GetCryptoCurrencyStatusSyncUseCase(
|
||||
private val currencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
) {
|
||||
|
||||
// multi-currency
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencyId: CryptoCurrency.ID,
|
||||
isSingleWalletWithTokens: Boolean = false,
|
||||
): Either<CurrencyStatusError, CryptoCurrencyStatus> {
|
||||
return currencyStatusOperations.getCurrencyStatusSync(userWalletId, cryptoCurrencyId, isSingleWalletWithTokens)
|
||||
.mapLeft { error -> error.mapToCurrencyError() }
|
||||
}
|
||||
|
||||
// single-currency
|
||||
suspend operator fun invoke(userWalletId: UserWalletId): Either<CurrencyStatusError, CryptoCurrencyStatus> {
|
||||
return currencyStatusOperations.getPrimaryCurrencyStatusSync(userWalletId)
|
||||
.mapLeft { error -> error.mapToCurrencyError() }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.error.mapper.mapToCurrencyError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
/**
|
||||
* Use case for fetching the status of a cryptocurrency associated with a user wallet.
|
||||
*
|
||||
*/
|
||||
class GetCurrencyStatusUpdatesUseCase(
|
||||
private val currencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Invokes the use case.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user's wallet.
|
||||
* @param currencyId The unique identifier of the cryptocurrency.
|
||||
* @param isSingleWalletWithTokens Indicates whether the user wallet contains only one token on card (old cards)
|
||||
* @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation.
|
||||
*/
|
||||
operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
isSingleWalletWithTokens: Boolean,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return flow {
|
||||
emitAll(
|
||||
getCurrencyStatus(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = currencyId,
|
||||
isSingleWalletWithTokens = isSingleWalletWithTokens,
|
||||
),
|
||||
)
|
||||
}.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
private suspend fun getCurrencyStatus(
|
||||
userWalletId: UserWalletId,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
isSingleWalletWithTokens: Boolean,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
val currencyFlow = currencyStatusOperations.getCurrencyStatusFlow(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = currencyId,
|
||||
isSingleWalletWithTokens = isSingleWalletWithTokens,
|
||||
)
|
||||
|
||||
return currencyFlow.map { maybeCurrency ->
|
||||
maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,25 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.error.mapper.mapToTokenListError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class GetCryptoCurrencyStatusesSyncUseCase(
|
||||
class GetMultiCryptoCurrencyStatusUseCase(
|
||||
private val currencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(userWalletId: UserWalletId): Either<TokenListError, List<CryptoCurrencyStatus>> {
|
||||
/**
|
||||
* Returns synchronously list of cryptocurrency statuses for Multi-Currency wallet
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user's wallet.
|
||||
* @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation.
|
||||
*/
|
||||
suspend fun invokeMultiWalletSync(userWalletId: UserWalletId): Either<TokenListError, List<CryptoCurrencyStatus>> {
|
||||
return currencyStatusOperations.getCurrenciesStatusesSync(userWalletId)
|
||||
.mapLeft { error -> error.mapToTokenListError() }
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.error.mapper.mapToCurrencyError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
/**
|
||||
* Use case for fetching the status of the primary cryptocurrency associated with a user wallet.
|
||||
*
|
||||
* @property dispatchers Provides coroutine dispatchers.
|
||||
*/
|
||||
class GetPrimaryCurrencyStatusUpdatesUseCase(
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val currencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Invokes the use case.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user's wallet.
|
||||
* @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation.
|
||||
*/
|
||||
operator fun invoke(userWalletId: UserWalletId): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return flow {
|
||||
emitAll(getPrimaryCurrency(userWalletId))
|
||||
}.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
private suspend fun getPrimaryCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return currencyStatusOperations.getPrimaryCurrencyStatusFlow(userWalletId).map { maybeCurrency ->
|
||||
maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.error.mapper.mapToCurrencyError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
/**
|
||||
* Use case for fetching the status of a cryptocurrency associated with a user wallet.
|
||||
*
|
||||
*/
|
||||
class GetSingleCryptoCurrencyStatusUseCase(
|
||||
private val currencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Returns cryptocurrency status flow for Multi-Currency wallet
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user's wallet.
|
||||
* @param currencyId The unique identifier of the cryptocurrency.
|
||||
* @param isSingleWalletWithTokens Indicates whether the user wallet contains only one token on card (old cards)
|
||||
* @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation.
|
||||
*/
|
||||
fun invokeMultiWallet(
|
||||
userWalletId: UserWalletId,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
isSingleWalletWithTokens: Boolean,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return flow {
|
||||
emitAll(
|
||||
getCurrencyStatus(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = currencyId,
|
||||
isSingleWalletWithTokens = isSingleWalletWithTokens,
|
||||
),
|
||||
)
|
||||
}.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cryptocurrency status flow for primary currency for Single-Currency wallet
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user's wallet.
|
||||
* @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation.
|
||||
*/
|
||||
fun invokeSingleWallet(userWalletId: UserWalletId): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return flow {
|
||||
emitAll(
|
||||
currencyStatusOperations.getPrimaryCurrencyStatusFlow(userWalletId).map { maybeCurrency ->
|
||||
maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError)
|
||||
},
|
||||
)
|
||||
}.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns synchronously cryptocurrency status for Multi-Currency wallet
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user's wallet.
|
||||
* @param cryptoCurrencyId The unique identifier of the cryptocurrency.
|
||||
* @param isSingleWalletWithTokens Indicates whether the user wallet contains only one token on card (old cards)
|
||||
* @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation.
|
||||
*/
|
||||
suspend fun invokeMultiWalletSync(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencyId: CryptoCurrency.ID,
|
||||
isSingleWalletWithTokens: Boolean = false,
|
||||
): Either<CurrencyStatusError, CryptoCurrencyStatus> {
|
||||
return currencyStatusOperations.getCurrencyStatusSync(userWalletId, cryptoCurrencyId, isSingleWalletWithTokens)
|
||||
.mapLeft { error -> error.mapToCurrencyError() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns synchronously cryptocurrency status for primary currency for Single-Currency wallet
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user's wallet.
|
||||
* @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation.
|
||||
*/
|
||||
suspend fun invokeSingleWalletSync(userWalletId: UserWalletId): Either<CurrencyStatusError, CryptoCurrencyStatus> {
|
||||
return currencyStatusOperations.getPrimaryCurrencyStatusSync(userWalletId)
|
||||
.mapLeft { error -> error.mapToCurrencyError() }
|
||||
}
|
||||
|
||||
private suspend fun getCurrencyStatus(
|
||||
userWalletId: UserWalletId,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
isSingleWalletWithTokens: Boolean,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
val currencyFlow = currencyStatusOperations.getCurrencyStatusFlow(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = currencyId,
|
||||
isSingleWalletWithTokens = isSingleWalletWithTokens,
|
||||
)
|
||||
|
||||
return currencyFlow.map { maybeCurrency ->
|
||||
maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,6 @@ package com.tangem.domain.tokens
|
|||
*/
|
||||
interface TokensFeatureToggles {
|
||||
|
||||
val isNetworksLoadingRefactoringEnabled: Boolean
|
||||
|
||||
val isQuotesLoadingRefactoringEnabled: Boolean
|
||||
|
||||
val isStakingLoadingRefactoringEnabled: Boolean
|
||||
|
|
|
|||
|
|
@ -2,12 +2,10 @@ package com.tangem.domain.tokens
|
|||
|
||||
import arrow.core.Either
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.catch
|
||||
import arrow.core.raise.either
|
||||
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
|
|
@ -15,14 +13,9 @@ import kotlinx.coroutines.delay
|
|||
* Use case responsible for fetching currency status information, including network status
|
||||
* and quotes for a given cryptocurrency. It provides methods to fetch currency status either
|
||||
* by providing a specific currency ID or fetching the status of the primary currency.
|
||||
*
|
||||
* @param networksRepository The repository for retrieving network-related data.
|
||||
*/
|
||||
|
||||
class UpdateDelayedNetworkStatusUseCase(
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
private val tokensFeatureToggles: TokensFeatureToggles,
|
||||
) {
|
||||
|
||||
/**
|
||||
|
|
@ -30,37 +23,24 @@ class UpdateDelayedNetworkStatusUseCase(
|
|||
*
|
||||
* @param userWalletId The ID of the user's wallet.
|
||||
* @param network Network of the cryptocurrency.
|
||||
* @param refresh Indicates whether to force a refresh of the status data.
|
||||
* @return An [Either] representing success (Right) or an error (Left) in fetching the status.
|
||||
*/
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
delayMillis: Long = 0L,
|
||||
refresh: Boolean = false,
|
||||
): Either<CurrencyStatusError, Unit> {
|
||||
delay(delayMillis)
|
||||
return either {
|
||||
fetchNetworkStatus(userWalletId, network, refresh)
|
||||
fetchNetworkStatus(userWalletId, network)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun Raise<CurrencyStatusError>.fetchNetworkStatus(
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
refresh: Boolean,
|
||||
) {
|
||||
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
singleNetworkStatusFetcher(
|
||||
params = SingleNetworkStatusFetcher.Params(userWalletId = userWalletId, network = network),
|
||||
)
|
||||
.mapLeft { CurrencyStatusError.DataError(it) }
|
||||
} else {
|
||||
catch(
|
||||
block = { networksRepository.getNetworkStatusesSync(userWalletId, setOf(network), refresh) },
|
||||
) {
|
||||
raise(CurrencyStatusError.DataError(it))
|
||||
}
|
||||
}
|
||||
private suspend fun Raise<CurrencyStatusError>.fetchNetworkStatus(userWalletId: UserWalletId, network: Network) {
|
||||
singleNetworkStatusFetcher(
|
||||
params = SingleNetworkStatusFetcher.Params(userWalletId = userWalletId, network = network),
|
||||
)
|
||||
.mapLeft(CurrencyStatusError::DataError)
|
||||
.bind()
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,6 @@ import com.tangem.domain.tokens.TokensFeatureToggles
|
|||
import com.tangem.domain.tokens.model.*
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.tokens.utils.CurrencyStatusProxyCreator
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
|
@ -33,7 +32,6 @@ import kotlinx.coroutines.flow.*
|
|||
*
|
||||
* @property currenciesRepository repository for currencies
|
||||
* @property quotesRepository repository for quotes
|
||||
* @property networksRepository repository for networks
|
||||
* @property stakingRepository repository for staking
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -43,7 +41,6 @@ abstract class BaseCurrencyStatusOperations(
|
|||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val quotesRepositoryV2: QuotesRepositoryV2,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
|
|
@ -203,24 +200,14 @@ abstract class BaseCurrencyStatusOperations(
|
|||
?.right()
|
||||
?: Error.EmptyQuotes.left()
|
||||
|
||||
val networkStatuses = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
singleNetworkStatusSupplier(
|
||||
params = SingleNetworkStatusProducer.Params(
|
||||
userWalletId = userWalletId,
|
||||
network = currency.network,
|
||||
),
|
||||
)
|
||||
.firstOrNull()
|
||||
.right()
|
||||
} else {
|
||||
networksRepository.getNetworkStatusesSync(
|
||||
val networkStatuses = singleNetworkStatusSupplier(
|
||||
params = SingleNetworkStatusProducer.Params(
|
||||
userWalletId = userWalletId,
|
||||
networks = setOf(currency.network),
|
||||
refresh = false,
|
||||
)
|
||||
.firstOrNull { it.network == currency.network }
|
||||
.right()
|
||||
}
|
||||
network = currency.network,
|
||||
),
|
||||
)
|
||||
.firstOrNull()
|
||||
.right()
|
||||
|
||||
val yieldBalances = getYieldBalanceSync(userWalletId, currency)
|
||||
|
||||
|
|
@ -270,7 +257,7 @@ abstract class BaseCurrencyStatusOperations(
|
|||
val nonEmptyCurrencies =
|
||||
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId).toNonEmptyListOrNull()
|
||||
?: return emptyList<CryptoCurrencyStatus>().right()
|
||||
val (networks, currenciesIds) = getIds(nonEmptyCurrencies)
|
||||
val (_, currenciesIds) = getIds(nonEmptyCurrencies)
|
||||
val rawIds = currenciesIds.mapNotNull { it.rawCurrencyId }.toSet()
|
||||
|
||||
val quotes = if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
|
||||
|
|
@ -279,16 +266,13 @@ abstract class BaseCurrencyStatusOperations(
|
|||
quotesRepository.getQuotesSync(rawIds, false).right()
|
||||
}
|
||||
|
||||
val networkStatuses = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
multiNetworkStatusSupplier(
|
||||
params = MultiNetworkStatusProducer.Params(userWalletId = userWalletId),
|
||||
)
|
||||
.firstOrNull()
|
||||
.orEmpty()
|
||||
.right()
|
||||
} else {
|
||||
networksRepository.getNetworkStatusesSync(userWalletId, networks, false).right()
|
||||
}
|
||||
val networkStatuses = multiNetworkStatusSupplier(
|
||||
params = MultiNetworkStatusProducer.Params(userWalletId = userWalletId),
|
||||
)
|
||||
.firstOrNull()
|
||||
.orEmpty()
|
||||
.right()
|
||||
|
||||
val yieldBalances = getYieldBalancesSync(userWalletId, nonEmptyCurrencies)
|
||||
|
||||
return currencyStatusProxyCreator.createCurrenciesStatuses(
|
||||
|
|
@ -326,25 +310,11 @@ abstract class BaseCurrencyStatusOperations(
|
|||
)
|
||||
}
|
||||
|
||||
val networkStatus = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
singleNetworkStatusSupplier(
|
||||
params = SingleNetworkStatusProducer.Params(
|
||||
userWalletId = userWalletId,
|
||||
network = currency.network,
|
||||
),
|
||||
)
|
||||
.firstOrNull()
|
||||
.right()
|
||||
} else {
|
||||
catch(
|
||||
block = {
|
||||
networksRepository.getNetworkStatusesSync(userWalletId, setOf(currency.network))
|
||||
.firstOrNull { it.network == currency.network }
|
||||
.right()
|
||||
},
|
||||
catch = { Error.DataError(it).left() },
|
||||
)
|
||||
}
|
||||
val networkStatus = singleNetworkStatusSupplier(
|
||||
params = SingleNetworkStatusProducer.Params(userWalletId = userWalletId, network = currency.network),
|
||||
)
|
||||
.firstOrNull()
|
||||
.right()
|
||||
|
||||
val yieldBalances = getYieldBalanceSync(userWalletId, currency)
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import com.tangem.domain.tokens.error.TokenListError
|
|||
import com.tangem.domain.tokens.model.*
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.tokens.utils.extractAddress
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
|
@ -43,7 +42,6 @@ class CachedCurrenciesStatusesOperations(
|
|||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
quotesRepositoryV2: QuotesRepositoryV2,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
|
|
@ -58,7 +56,6 @@ class CachedCurrenciesStatusesOperations(
|
|||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
quotesRepositoryV2 = quotesRepositoryV2,
|
||||
networksRepository = networksRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
|
|
@ -156,7 +153,7 @@ class CachedCurrenciesStatusesOperations(
|
|||
|
||||
combine(
|
||||
flow = getQuotes(currenciesIds),
|
||||
flow2 = getNetworksStatuses(userWalletId, networks),
|
||||
flow2 = getNetworkStatusesUpdates(userWalletId, networks),
|
||||
flow3 = getYieldBalances(userWalletId, currencies),
|
||||
flow4 = fetchingState.map {
|
||||
val state = it[userWalletId] ?: return@map false
|
||||
|
|
@ -184,13 +181,9 @@ class CachedCurrenciesStatusesOperations(
|
|||
coroutineScope {
|
||||
awaitAll(
|
||||
async {
|
||||
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
multiNetworkStatusFetcher(
|
||||
params = MultiNetworkStatusFetcher.Params(userWalletId, networks),
|
||||
)
|
||||
} else {
|
||||
networksRepository.fetchNetworkStatuses(userWalletId, networks)
|
||||
}
|
||||
multiNetworkStatusFetcher(
|
||||
params = MultiNetworkStatusFetcher.Params(userWalletId = userWalletId, networks = networks),
|
||||
)
|
||||
},
|
||||
async {
|
||||
val rawCurrenciesIds = currenciesIds.mapNotNullTo(mutableSetOf()) { it.rawCurrencyId }
|
||||
|
|
@ -327,44 +320,12 @@ class CachedCurrenciesStatusesOperations(
|
|||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): EitherFlow<Error, Set<NetworkStatus>> {
|
||||
return if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
singleNetworkStatusSupplier(
|
||||
params = SingleNetworkStatusProducer.Params(userWalletId = userWalletId, network = network),
|
||||
)
|
||||
.map<NetworkStatus, Either<Error, Set<NetworkStatus>>> { setOf(it).right() }
|
||||
.distinctUntilChanged()
|
||||
.onEmpty { emit(Error.EmptyNetworksStatuses.left()) }
|
||||
} else {
|
||||
networksRepository.getNetworkStatusesUpdates(userWalletId, setOf(network))
|
||||
.map<Set<NetworkStatus>, Either<Error, Set<NetworkStatus>>> { it.right() }
|
||||
.retryWhen { cause, _ ->
|
||||
emit(Error.DataError(cause).left())
|
||||
// adding delay before retry to avoid spam when flow restarted
|
||||
delay(RETRY_DELAY)
|
||||
true
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.onEmpty { emit(Error.EmptyNetworksStatuses.left()) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun getNetworksStatuses(
|
||||
userWalletId: UserWalletId,
|
||||
networks: NonEmptySet<Network>,
|
||||
): EitherFlow<TokenListError, Set<NetworkStatus>> {
|
||||
return if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
getNetworkStatusesUpdates(userWalletId, networks)
|
||||
} else {
|
||||
networksRepository.getNetworkStatusesUpdates(userWalletId, networks)
|
||||
.map<Set<NetworkStatus>, Either<TokenListError, Set<NetworkStatus>>> { it.right() }
|
||||
.retryWhen { cause, _ ->
|
||||
emit(TokenListError.DataError(cause).left())
|
||||
// adding delay before retry to avoid spam when flow restarted
|
||||
delay(RETRY_DELAY)
|
||||
true
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
return singleNetworkStatusSupplier(
|
||||
params = SingleNetworkStatusProducer.Params(userWalletId = userWalletId, network = network),
|
||||
)
|
||||
.map<NetworkStatus, Either<Error, Set<NetworkStatus>>> { setOf(it).right() }
|
||||
.distinctUntilChanged()
|
||||
.onEmpty { emit(Error.EmptyNetworksStatuses.left()) }
|
||||
}
|
||||
|
||||
private fun getYieldBalances(
|
||||
|
|
|
|||
|
|
@ -1,197 +0,0 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.core.error.DataError
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.mock.MockNetworks
|
||||
import com.tangem.domain.tokens.mock.MockQuotes
|
||||
import com.tangem.domain.tokens.mock.MockTokens
|
||||
import com.tangem.domain.tokens.mock.MockTokensStates
|
||||
import com.tangem.domain.tokens.model.*
|
||||
import com.tangem.domain.tokens.operations.CachedCurrenciesStatusesOperations
|
||||
import com.tangem.domain.tokens.repository.MockCurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.MockNetworksRepository
|
||||
import com.tangem.domain.tokens.repository.MockQuotesRepository
|
||||
import com.tangem.domain.tokens.repository.MockStakingRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.mockk
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal class GetPrimaryCurrencyStatusUpdatesUseCaseTest {
|
||||
|
||||
private val dispatchers = TestingCoroutineDispatcherProvider()
|
||||
private val userWalletId = UserWalletId(value = null)
|
||||
|
||||
@Test
|
||||
fun `when all data received then token should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = MockTokensStates.loadedTokensStates.first().right()
|
||||
|
||||
val useCase = getUseCase()
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when token getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = CurrencyStatusError.DataError(DataError.NetworkError.NoInternetConnection).left()
|
||||
|
||||
val useCase = getUseCase(token = DataError.NetworkError.NoInternetConnection.left())
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when quotes getting failed then currency with no quote status should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = MockTokensStates.noQuotesTokensStatuses.first().right()
|
||||
|
||||
val useCase = getUseCase(quotes = flowOf(DataError.NetworkError.NoInternetConnection.left()))
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when networks statuses getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = CurrencyStatusError.DataError(DataError.NetworkError.NoInternetConnection).left()
|
||||
|
||||
val useCase = getUseCase(statuses = flowOf(DataError.NetworkError.NoInternetConnection.left()))
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when networks statuses flow is empty then error should be received`() = runTest {
|
||||
val expectedResult = CurrencyStatusError.UnableToCreateCurrency.left()
|
||||
|
||||
val useCase = getUseCase(statuses = flowOf())
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when quotes flow is empty then no quote status should be received`() = runTest {
|
||||
val expectedResult = MockTokensStates.noQuotesTokensStatuses.first().right()
|
||||
|
||||
val useCase = getUseCase(quotes = flowOf(emptySet<Quote>().right()))
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when quotes are empty and statuses are verified then token without quote should be received`() = runTest {
|
||||
val expectedResult = with(MockTokensStates.tokenState1) {
|
||||
copy(
|
||||
value = CryptoCurrencyStatus.NoQuote(
|
||||
amount = BigDecimal.TEN,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
networkAddress = NetworkAddress.Single(
|
||||
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
||||
),
|
||||
yieldBalance = null,
|
||||
sources = CryptoCurrencyStatus.Sources(),
|
||||
),
|
||||
)
|
||||
}
|
||||
.right()
|
||||
|
||||
val useCase = getUseCase(
|
||||
statuses = flowOf(MockNetworks.verifiedNetworksStatuses.right()),
|
||||
quotes = flowOf(emptySet<Quote>().right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when quotes are loaded and statuses are empty then error be received`() = runTest {
|
||||
val expectedResult = CurrencyStatusError.UnableToCreateCurrency.left()
|
||||
|
||||
val useCase = getUseCase(
|
||||
statuses = flowOf(emptySet<NetworkStatus>().right()),
|
||||
quotes = flowOf(MockQuotes.quotes.right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
private fun getUseCase(
|
||||
token: Either<DataError, CryptoCurrency> = MockTokens.token1.right(),
|
||||
removeCurrencyResult: Either<DataError, Unit> = Unit.right(),
|
||||
quotes: Flow<Either<DataError, Set<Quote>>> = flowOf(MockQuotes.quotes.right()),
|
||||
statuses: Flow<Either<DataError, Set<NetworkStatus>>> = flowOf(MockNetworks.verifiedNetworksStatuses.right()),
|
||||
) = GetPrimaryCurrencyStatusUpdatesUseCase(
|
||||
currencyStatusOperations = CachedCurrenciesStatusesOperations(
|
||||
currenciesRepository = MockCurrenciesRepository(
|
||||
sortTokensResult = Unit.right(),
|
||||
removeCurrencyResult = removeCurrencyResult,
|
||||
token = token,
|
||||
tokens = flowOf(),
|
||||
isGrouped = flowOf(),
|
||||
isSortedByBalance = flowOf(),
|
||||
),
|
||||
quotesRepository = MockQuotesRepository(quotes),
|
||||
networksRepository = MockNetworksRepository(statuses),
|
||||
stakingRepository = MockStakingRepository(),
|
||||
|
||||
tokensFeatureToggles = object : TokensFeatureToggles {
|
||||
override val isNetworksLoadingRefactoringEnabled: Boolean = false
|
||||
override val isQuotesLoadingRefactoringEnabled: Boolean = false
|
||||
override val isStakingLoadingRefactoringEnabled: Boolean = false
|
||||
},
|
||||
singleNetworkStatusSupplier = mockk(),
|
||||
multiNetworkStatusFetcher = mockk(),
|
||||
multiNetworkStatusSupplier = mockk(),
|
||||
multiQuoteFetcher = mockk(),
|
||||
singleQuoteSupplier = mockk(),
|
||||
quotesRepositoryV2 = mockk(),
|
||||
singleYieldBalanceSupplier = mockk(),
|
||||
multiYieldBalanceFetcher = mockk(),
|
||||
),
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
|
@ -7,12 +7,10 @@ import com.tangem.blockchain.extensions.SimpleResult
|
|||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.networks.single.SingleNetworkStatusProducer
|
||||
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyAmountStatus
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.transaction.error.AssociateAssetError
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
|
@ -23,9 +21,7 @@ class AssociateAssetUseCase(
|
|||
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
private val tokensFeatureToggles: TokensFeatureToggles,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
|
|
@ -59,20 +55,13 @@ class AssociateAssetUseCase(
|
|||
}
|
||||
|
||||
private suspend fun isBalanceZero(userWalletId: UserWalletId, currency: CryptoCurrency): Boolean {
|
||||
val networkStatus = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
singleNetworkStatusSupplier(
|
||||
params = SingleNetworkStatusProducer.Params(
|
||||
userWalletId = userWalletId,
|
||||
network = currency.network,
|
||||
),
|
||||
)
|
||||
.firstOrNull()
|
||||
} else {
|
||||
networksRepository.getNetworkStatusesSync(
|
||||
val networkStatus = singleNetworkStatusSupplier(
|
||||
params = SingleNetworkStatusProducer.Params(
|
||||
userWalletId = userWalletId,
|
||||
networks = setOf(currency.network),
|
||||
).find { it.network == currency.network }
|
||||
}
|
||||
network = currency.network,
|
||||
),
|
||||
)
|
||||
.firstOrNull()
|
||||
|
||||
val networkCoinAmountStatus = (networkStatus?.value as? NetworkStatus.Verified)
|
||||
?.amounts
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
|||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.demo.DemoTransactionSender
|
||||
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
|
|
@ -33,7 +32,6 @@ class SendTransactionUseCase(
|
|||
private val transactionRepository: TransactionRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
private val tokensFeatureToggles: TokensFeatureToggles,
|
||||
) {
|
||||
suspend operator fun invoke(
|
||||
txsData: List<TransactionData>,
|
||||
|
|
@ -80,16 +78,15 @@ class SendTransactionUseCase(
|
|||
}
|
||||
|
||||
cardSdkConfigRepository.setLinkedTerminal(linkedTerminal)
|
||||
|
||||
return sendResult
|
||||
.onRight {
|
||||
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
singleNetworkStatusFetcher(
|
||||
params = SingleNetworkStatusFetcher.Params(
|
||||
userWalletId = userWallet.walletId,
|
||||
network = network,
|
||||
),
|
||||
)
|
||||
}
|
||||
singleNetworkStatusFetcher(
|
||||
params = SingleNetworkStatusFetcher.Params(
|
||||
userWalletId = userWallet.walletId,
|
||||
network = network,
|
||||
),
|
||||
)
|
||||
}
|
||||
.fold(
|
||||
ifRight = { result -> result.hashes.right() },
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
package com.tangem.domain.walletconnect.model
|
||||
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class WcPairRequest(
|
||||
val uri: String,
|
||||
val source: Source,
|
||||
val userWalletId: UserWalletId,
|
||||
) {
|
||||
enum class Source { QR, DEEPLINK, CLIPBOARD, ETC }
|
||||
}
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
package com.tangem.domain.walletconnect.model
|
||||
|
||||
import com.domain.blockaid.models.dapp.CheckDAppResult
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSession
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
data class WcSession(
|
||||
val wallet: UserWallet,
|
||||
val networks: Set<Network>,
|
||||
val sdkModel: WcSdkSession,
|
||||
val securityStatus: CheckDAppResult,
|
||||
)
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.domain.wallets.usecase
|
||||
|
||||
import com.tangem.common.card.FirmwareVersion
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.common.services.Result
|
||||
import com.tangem.domain.common.TwinCardNumber
|
||||
|
|
@ -30,11 +31,19 @@ class GetCardImageUseCase(
|
|||
* @param cardId card id
|
||||
* @param cardPublicKey card public key
|
||||
*/
|
||||
suspend operator fun invoke(cardId: String, cardPublicKey: ByteArray, size: ArtworkSize): ArtworkModel {
|
||||
suspend operator fun invoke(
|
||||
cardId: String,
|
||||
cardPublicKey: ByteArray,
|
||||
manufacturerName: String,
|
||||
firmwareVersion: FirmwareVersion,
|
||||
size: ArtworkSize,
|
||||
): ArtworkModel {
|
||||
return if (cardSdkFeatureToggles.isNewArtworkLoadingEnabled) {
|
||||
val result = cardArtworksProvider.getArtwork(
|
||||
cardId = cardId,
|
||||
cardPublicKey = cardPublicKey,
|
||||
manufacturerName = manufacturerName,
|
||||
firmwareVersion = firmwareVersion,
|
||||
size = size,
|
||||
)
|
||||
when (result) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.compose.ui.Modifier
|
|||
import com.tangem.core.decompose.navigation.DummyRouter
|
||||
import com.tangem.core.navigation.url.DummyUrlOpener
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.details.component.DetailsComponent
|
||||
import com.tangem.features.details.entity.DetailsFooterUM
|
||||
import com.tangem.features.details.entity.DetailsUM
|
||||
|
|
@ -18,7 +19,12 @@ internal class PreviewDetailsComponent : DetailsComponent {
|
|||
private val previewBlocks = runBlocking {
|
||||
ItemsBuilder(
|
||||
router = DummyRouter(),
|
||||
).buildAll(isWalletConnectAvailable = true, onSupportClick = {}, onBuyClick = {})
|
||||
).buildAll(
|
||||
isWalletConnectAvailable = true,
|
||||
userWalletId = UserWalletId(""),
|
||||
onSupportClick = {},
|
||||
onBuyClick = {},
|
||||
)
|
||||
}
|
||||
|
||||
private val previewFooter = DetailsFooterUM(
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ internal class DetailsModel @Inject constructor(
|
|||
items = MutableStateFlow(
|
||||
itemsBuilder.buildAll(
|
||||
isWalletConnectAvailable = isWalletConnectAvailable,
|
||||
userWalletId = params.userWalletId,
|
||||
onSupportClick = ::sendFeedback,
|
||||
onBuyClick = ::onBuyClick,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.core.decompose.navigation.Router
|
|||
import com.tangem.core.ui.components.block.model.BlockUM
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.details.entity.DetailsItemUM
|
||||
import com.tangem.features.details.impl.BuildConfig
|
||||
import com.tangem.features.details.impl.R
|
||||
|
|
@ -19,20 +20,21 @@ internal class ItemsBuilder @Inject constructor(private val router: Router) {
|
|||
|
||||
fun buildAll(
|
||||
isWalletConnectAvailable: Boolean,
|
||||
userWalletId: UserWalletId,
|
||||
onSupportClick: () -> Unit,
|
||||
onBuyClick: () -> Unit,
|
||||
): ImmutableList<DetailsItemUM> = buildList {
|
||||
buildWalletConnectBlock(isWalletConnectAvailable)?.let(::add)
|
||||
buildWalletConnectBlock(isWalletConnectAvailable, userWalletId)?.let(::add)
|
||||
buildUserWalletListBlock().let(::add)
|
||||
buildShopBlock(onBuyClick).let(::add)
|
||||
buildSettingsBlock().let(::add)
|
||||
buildSupportBlock(onSupportClick).let(::add)
|
||||
}.toImmutableList()
|
||||
|
||||
private fun buildWalletConnectBlock(isWalletConnectAvailable: Boolean): DetailsItemUM? {
|
||||
private fun buildWalletConnectBlock(isWalletConnectAvailable: Boolean, userWalletId: UserWalletId): DetailsItemUM? {
|
||||
return if (isWalletConnectAvailable) {
|
||||
DetailsItemUM.WalletConnect(
|
||||
onClick = { router.push(AppRoute.WalletConnectSessions) },
|
||||
onClick = { router.push(AppRoute.WalletConnectSessions(userWalletId)) },
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
|
|
|||
|
|
@ -87,6 +87,8 @@ internal class UserWalletsFetcher @Inject constructor(
|
|||
wallets.forEach { wallet ->
|
||||
val artwork = getCardImageUseCase(
|
||||
cardId = wallet.cardId,
|
||||
manufacturerName = wallet.scanResponse.card.manufacturer.name,
|
||||
firmwareVersion = wallet.scanResponse.card.firmwareVersion.toSdkFirmwareVersion(),
|
||||
cardPublicKey = wallet.scanResponse.card.cardPublicKey,
|
||||
size = ArtworkSize.SMALL,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -15,10 +15,6 @@ import com.tangem.features.nft.collections.NFTCollectionsComponent
|
|||
import com.tangem.features.nft.collections.entity.NFTCollectionsStateUM
|
||||
import com.tangem.features.nft.collections.entity.NFTCollectionsUM
|
||||
import com.tangem.features.nft.collections.entity.transformer.*
|
||||
import com.tangem.features.nft.collections.entity.transformer.ChangeCollectionExpandedStateTransformer
|
||||
import com.tangem.features.nft.collections.entity.transformer.ToggleSearchBarTransformer
|
||||
import com.tangem.features.nft.collections.entity.transformer.UpdateDataStateTransformer
|
||||
import com.tangem.features.nft.collections.entity.transformer.UpdateSearchQueryTransformer
|
||||
import com.tangem.features.nft.impl.R
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.features.onboarding.v2.multiwallet.impl.child
|
||||
|
||||
import com.tangem.common.card.Card.Manufacturer
|
||||
import com.tangem.common.card.FirmwareVersion
|
||||
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.MultiWalletInnerNavigationState
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState
|
||||
|
|
@ -18,6 +20,8 @@ class MultiWalletChildParams(
|
|||
data class BackupCardInfo(
|
||||
val cardId: String,
|
||||
val cardPublicKey: ByteArray,
|
||||
val manufacturer: Manufacturer,
|
||||
val firmwareVersion: FirmwareVersion,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
|
|
|||
|
|
@ -206,6 +206,8 @@ class MultiWalletBackupModel @Inject constructor(
|
|||
val backupCardInfo = MultiWalletChildParams.Backup.BackupCardInfo(
|
||||
cardId = result.data.cardId,
|
||||
cardPublicKey = result.data.cardPublicKey,
|
||||
manufacturer = result.data.manufacturer,
|
||||
firmwareVersion = result.data.firmwareVersion,
|
||||
)
|
||||
params.backups.update {
|
||||
it.copy(
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
cardId = backup.card2.cardId,
|
||||
cardPublicKey = backup.card2.cardPublicKey,
|
||||
size = ArtworkSize.LARGE,
|
||||
manufacturerName = backup.card2.manufacturer.name,
|
||||
firmwareVersion = backup.card2.firmwareVersion,
|
||||
)
|
||||
_uiState.update {
|
||||
it.copy(artwork2 = ArtworkUM(artwork.verifiedArtwork, artwork.defaultUrl))
|
||||
|
|
@ -97,6 +99,8 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
cardId = backup.card3.cardId,
|
||||
cardPublicKey = backup.card3.cardPublicKey,
|
||||
size = ArtworkSize.LARGE,
|
||||
manufacturerName = backup.card3.manufacturer.name,
|
||||
firmwareVersion = backup.card3.firmwareVersion,
|
||||
)
|
||||
_uiState.update {
|
||||
it.copy(artwork3 = ArtworkUM(artwork.verifiedArtwork, artwork.defaultUrl))
|
||||
|
|
@ -170,6 +174,8 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
cardId = params.scanResponse.card.cardId,
|
||||
cardPublicKey = params.scanResponse.card.cardPublicKey,
|
||||
size = ArtworkSize.LARGE,
|
||||
manufacturerName = params.scanResponse.card.manufacturer.name,
|
||||
firmwareVersion = params.scanResponse.card.firmwareVersion.toSdkFirmwareVersion(),
|
||||
)
|
||||
|
||||
_uiState.update {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import com.tangem.domain.exchange.RampStateManager
|
|||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.onramp.GetLegacyTopUpUrlUseCase
|
||||
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.model.NetworkAddress
|
||||
|
|
@ -39,7 +39,7 @@ import javax.inject.Inject
|
|||
internal class OnboardingNoteTopUpModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
|
||||
private val userWalletBuilderFactory: UserWalletBuilder.Factory,
|
||||
private val getLegacyTopUpUrlUseCase: GetLegacyTopUpUrlUseCase,
|
||||
|
|
@ -137,8 +137,11 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
|
||||
private fun observeCryptoCurrencyStatus() {
|
||||
val userWalletId = userWallet?.walletId ?: return
|
||||
getPrimaryCurrencyStatusUpdatesUseCase(userWalletId = userWalletId).map { it.getOrNull() }.filterNotNull()
|
||||
.onEach(::applyCryptoCurrencyStatusToState).launchIn(modelScope)
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWalletId = userWalletId)
|
||||
.map { it.getOrNull() }
|
||||
.filterNotNull()
|
||||
.onEach(::applyCryptoCurrencyStatusToState)
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun applyCryptoCurrencyStatusToState(status: CryptoCurrencyStatus) {
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ internal class OnboardingNoteModel @Inject constructor(
|
|||
cardId = cardInfo.cardId,
|
||||
cardPublicKey = cardInfo.cardPublicKey,
|
||||
size = ArtworkSize.LARGE,
|
||||
manufacturerName = cardInfo.manufacturer.name,
|
||||
firmwareVersion = cardInfo.firmwareVersion.toSdkFirmwareVersion(),
|
||||
)
|
||||
_uiState.update {
|
||||
it.copy(cardArtwork = ArtworkUM(artwork.verifiedArtwork, artwork.defaultUrl))
|
||||
|
|
|
|||
|
|
@ -7,18 +7,18 @@ import com.tangem.common.core.TangemError
|
|||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.common.ui.bottomsheet.receive.TokenReceiveBottomSheetConfig
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
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.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.common.ui.bottomsheet.receive.TokenReceiveBottomSheetConfig
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.navigation.share.ShareManager
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.clipboard.ClipboardManager
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.toWrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
|
|
@ -34,7 +34,7 @@ import com.tangem.domain.models.scan.ScanResponse
|
|||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onramp.GetLegacyTopUpUrlUseCase
|
||||
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.model.analytics.TokenReceiveAnalyticsEvent
|
||||
|
|
@ -77,7 +77,7 @@ internal class OnboardingTwinModel @Inject constructor(
|
|||
private val tangemSdkManager: TangemSdkManager,
|
||||
private val issuersConfigStorage: IssuersConfigStorage,
|
||||
private val cardRepository: CardRepository,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
|
||||
private val getLegacyTopUpUrlUseCase: GetLegacyTopUpUrlUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
|
|
@ -337,16 +337,16 @@ internal class OnboardingTwinModel @Inject constructor(
|
|||
setLoading(false)
|
||||
}
|
||||
|
||||
val cryptoCurrencyStatus =
|
||||
getPrimaryCurrencyStatusUpdatesUseCase.invoke(userWallet.walletId).firstOrNull()?.getOrNull()
|
||||
?: run {
|
||||
setLoading(false)
|
||||
Timber.e("Unable to get currency status")
|
||||
return@coroutineScope
|
||||
}
|
||||
val cryptoCurrencyStatus = getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWallet.walletId)
|
||||
.firstOrNull()?.getOrNull()
|
||||
?: run {
|
||||
setLoading(false)
|
||||
Timber.e("Unable to get currency status")
|
||||
return@coroutineScope
|
||||
}
|
||||
|
||||
launch {
|
||||
getPrimaryCurrencyStatusUpdatesUseCase.invoke(userWallet.walletId)
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWallet.walletId)
|
||||
.collect {
|
||||
it.onRight { status ->
|
||||
applyCryptoCurrencyStatusToState(status)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
|||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.onramp.GetHotCryptoUseCase
|
||||
import com.tangem.domain.onramp.model.HotCryptoCurrency
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyStatusSyncUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.features.onramp.hottokens.HotCryptoComponent
|
||||
import com.tangem.features.onramp.hottokens.converter.HotTokenItemStateConverter
|
||||
|
|
@ -45,7 +45,7 @@ internal class HotCryptoModel @Inject constructor(
|
|||
paramsContainer: ParamsContainer,
|
||||
getHotCryptoUseCase: GetHotCryptoUseCase,
|
||||
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getCryptoCurrencyStatusSyncUseCase: GetCryptoCurrencyStatusSyncUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -103,7 +103,10 @@ internal class HotCryptoModel @Inject constructor(
|
|||
|
||||
private fun onSuccessAdding(id: CryptoCurrency.ID) {
|
||||
modelScope.launch {
|
||||
getCryptoCurrencyStatusSyncUseCase(userWalletId = params.userWalletId, cryptoCurrencyId = id)
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync(
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrencyId = id,
|
||||
)
|
||||
.onRight {
|
||||
bottomSheetNavigation.dismiss()
|
||||
params.onTokenClick(it)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ internal class SendBalanceUpdater @AssistedInject constructor(
|
|||
userWalletId = userWallet.walletId,
|
||||
network = cryptoCurrency.network,
|
||||
delayMillis = delay,
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,9 +23,8 @@ import com.tangem.domain.feedback.models.FeedbackEmailType
|
|||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase
|
||||
import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
|
|
@ -72,8 +71,7 @@ internal class SendModel @Inject constructor(
|
|||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val router: Router,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
||||
|
|
@ -244,13 +242,13 @@ internal class SendModel @Inject constructor(
|
|||
isMultiCurrency: Boolean,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return if (isMultiCurrency) {
|
||||
getCurrencyStatusUpdatesUseCase(
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
isSingleWalletWithTokens = isSingleWalletWithToken,
|
||||
)
|
||||
} else {
|
||||
getPrimaryCurrencyStatusUpdatesUseCase(userWalletId = userWalletId)
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWalletId = userWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
|||
import com.tangem.domain.feedback.models.BlockchainErrorInfo
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
|
|
@ -60,7 +60,7 @@ internal class NFTSendModel @Inject constructor(
|
|||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val getCryptoCurrenciesUseCase: GetCryptoCurrenciesUseCase,
|
||||
private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
|
||||
private val createNFTTransferTransactionUseCase: CreateNFTTransferTransactionUseCase,
|
||||
private val getFeeUseCase: GetFeeUseCase,
|
||||
|
|
@ -183,7 +183,7 @@ internal class NFTSendModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun getCurrenciesStatusUpdates(isSingleWalletWithToken: Boolean) {
|
||||
getCurrencyStatusUpdatesUseCase(
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
isSingleWalletWithTokens = isSingleWalletWithToken,
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ import kotlin.properties.Delegates
|
|||
internal class SendModel @Inject constructor(
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val getCryptoCurrencyStatusSyncUseCase: GetCryptoCurrencyStatusSyncUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getWalletsUseCase: GetWalletsUseCase,
|
||||
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
|
||||
|
|
@ -325,13 +325,13 @@ internal class SendModel @Inject constructor(
|
|||
isMultiCurrency: Boolean,
|
||||
): Either<CurrencyStatusError, CryptoCurrencyStatus> {
|
||||
return if (isMultiCurrency) {
|
||||
getCryptoCurrencyStatusSyncUseCase(
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencyId = cryptoCurrency.id,
|
||||
isSingleWalletWithTokens = isSingleWalletWithToken,
|
||||
)
|
||||
} else {
|
||||
getCryptoCurrencyStatusSyncUseCase(userWalletId = userWalletId)
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeSingleWalletSync(userWalletId = userWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1048,7 +1048,6 @@ internal class SendModel @Inject constructor(
|
|||
userWalletId = userWallet.walletId,
|
||||
network = cryptoCurrency.network,
|
||||
delayMillis = BALANCE_UPDATE_DELAY,
|
||||
refresh = true,
|
||||
)
|
||||
},
|
||||
).awaitAll()
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ internal class StakingModel @Inject constructor(
|
|||
private val stateController: StakingStateController,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
|
||||
private val getMinimumTransactionAmountSyncUseCase: GetMinimumTransactionAmountSyncUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
|
|
@ -920,7 +920,7 @@ internal class StakingModel @Inject constructor(
|
|||
)
|
||||
},
|
||||
)
|
||||
getCurrencyStatusUpdatesUseCase(
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = cryptoCurrencyId,
|
||||
isSingleWalletWithTokens = false,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ internal class StakingBalanceUpdater @AssistedInject constructor(
|
|||
userWalletId = userWallet.walletId,
|
||||
network = cryptoCurrencyStatus.currency.network,
|
||||
delayMillis = delay,
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
|
|||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.quotes.QuotesRepositoryV2
|
||||
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyStatusesSyncUseCase
|
||||
import com.tangem.domain.tokens.GetMultiCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.GetCurrencyCheckUseCase
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.tokens.model.*
|
||||
|
|
@ -54,7 +54,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
private val userWalletManager: UserWalletManager,
|
||||
private val repository: SwapRepository,
|
||||
private val allowPermissionsHandler: AllowPermissionsHandler,
|
||||
private val getMultiCryptoCurrencyStatusUseCase: GetCryptoCurrencyStatusesSyncUseCase,
|
||||
private val getMultiCryptoCurrencyStatusUseCase: GetMultiCryptoCurrencyStatusUseCase,
|
||||
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
|
||||
private val sendTransactionUseCase: SendTransactionUseCase,
|
||||
private val createTransactionUseCase: CreateTransactionUseCase,
|
||||
|
|
@ -92,7 +92,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override suspend fun getTokensDataState(currency: CryptoCurrency): TokensDataStateExpress {
|
||||
val walletCurrencyStatuses = getMultiCryptoCurrencyStatusUseCase(userWalletId)
|
||||
val walletCurrencyStatuses = getMultiCryptoCurrencyStatusUseCase.invokeMultiWalletSync(userWalletId)
|
||||
.getOrElse { emptyList() }
|
||||
|
||||
val walletCurrencyStatusesExceptInitial = walletCurrencyStatuses
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.feature.swap.domain.di
|
||||
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyStatusesSyncUseCase
|
||||
import com.tangem.domain.tokens.GetMultiCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations
|
||||
import com.tangem.feature.swap.domain.*
|
||||
import dagger.Module
|
||||
|
|
@ -28,8 +28,8 @@ internal class SwapDomainModule {
|
|||
@Singleton
|
||||
fun providesGetCryptoCurrencyStatusUseCase(
|
||||
currencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
): GetCryptoCurrencyStatusesSyncUseCase {
|
||||
return GetCryptoCurrencyStatusesSyncUseCase(currencyStatusOperations)
|
||||
): GetMultiCryptoCurrencyStatusUseCase {
|
||||
return GetMultiCryptoCurrencyStatusUseCase(currencyStatusOperations)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ import com.tangem.domain.promo.models.StoryContentIds
|
|||
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
|
||||
import com.tangem.domain.settings.usercountry.models.UserCountry
|
||||
import com.tangem.domain.settings.usercountry.models.needApplyFCARestrictions
|
||||
import com.tangem.domain.tokens.*
|
||||
import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
|
||||
import com.tangem.domain.tokens.GetMinimumTransactionAmountSyncUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.UpdateDelayedNetworkStatusUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
|
|
@ -86,9 +89,8 @@ internal class SwapModel @Inject constructor(
|
|||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val analyticsErrorEventHandler: AnalyticsErrorHandler,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getCryptoCurrencyStatusUseCase: GetCryptoCurrencyStatusSyncUseCase,
|
||||
private val updateDelayedCurrencyStatusUseCase: UpdateDelayedNetworkStatusUseCase,
|
||||
private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val getCardInfoUseCase: GetCardInfoUseCase,
|
||||
|
|
@ -98,7 +100,7 @@ internal class SwapModel @Inject constructor(
|
|||
private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase,
|
||||
private val shouldShowStoriesUseCase: ShouldShowStoriesUseCase,
|
||||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
private val getUserCountryUseCase: GetUserCountryUseCase,
|
||||
getUserCountryUseCase: GetUserCountryUseCase,
|
||||
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
swapInteractorFactory: SwapInteractor.Factory,
|
||||
private val urlOpener: UrlOpener,
|
||||
|
|
@ -176,8 +178,12 @@ internal class SwapModel @Inject constructor(
|
|||
}
|
||||
|
||||
modelScope.launch(dispatchers.io) {
|
||||
val fromStatus = getCryptoCurrencyStatusUseCase(userWalletId, initialCurrencyFrom.id).getOrNull()
|
||||
val toStatus = initialCurrencyTo?.let { getCryptoCurrencyStatusUseCase(userWalletId, it.id).getOrNull() }
|
||||
val fromStatus =
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync(userWalletId, initialCurrencyFrom.id)
|
||||
.getOrNull()
|
||||
val toStatus = initialCurrencyTo?.let {
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync(userWalletId, it.id).getOrNull()
|
||||
}
|
||||
val wallet = getUserWalletUseCase(userWalletId).getOrNull()
|
||||
|
||||
if (fromStatus == null || wallet == null) {
|
||||
|
|
@ -861,7 +867,7 @@ internal class SwapModel @Inject constructor(
|
|||
) {
|
||||
Timber.d("Subscribe to ${coin.id} balance updates")
|
||||
|
||||
getCurrencyStatusUpdatesUseCase(
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = coin.id,
|
||||
isSingleWalletWithTokens = false,
|
||||
|
|
@ -1311,7 +1317,6 @@ internal class SwapModel @Inject constructor(
|
|||
userWalletId = userWalletId,
|
||||
network = network,
|
||||
delayMillis = UPDATE_BALANCE_DELAY_MILLIS,
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ import javax.inject.Inject
|
|||
@ModelScoped
|
||||
internal class TokenDetailsModel @Inject constructor(
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
|
||||
private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase,
|
||||
|
|
@ -117,7 +117,6 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
private val vibratorHapticManager: VibratorHapticManager,
|
||||
private val clipboardManager: ClipboardManager,
|
||||
private val getCryptoCurrencySyncUseCase: GetCryptoCurrencyStatusSyncUseCase,
|
||||
private val onrampFeatureToggles: OnrampFeatureToggles,
|
||||
private val shareManager: ShareManager,
|
||||
@GlobalUiMessageSender private val uiMessageSender: UiMessageSender,
|
||||
|
|
@ -219,7 +218,7 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
private fun initButtons() {
|
||||
// we need also init buttons before start all loading to avoid buttons blocking
|
||||
modelScope.launch {
|
||||
val currentCryptoCurrencyStatus = getCryptoCurrencySyncUseCase.invoke(
|
||||
val currentCryptoCurrencyStatus = getSingleCryptoCurrencyStatusUseCase.invokeMultiWalletSync(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencyId = cryptoCurrency.id,
|
||||
isSingleWalletWithTokens = false,
|
||||
|
|
@ -300,7 +299,7 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
|
||||
private fun subscribeOnCurrencyStatusUpdates() {
|
||||
modelScope.launch(dispatchers.main) {
|
||||
getCurrencyStatusUpdatesUseCase(
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
isSingleWalletWithTokens = userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(),
|
||||
|
|
@ -364,7 +363,6 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
updateDelayedCurrencyStatusUseCase(
|
||||
userWalletId = userWalletId,
|
||||
network = toCryptoCurrency.network,
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.tangem.core.decompose.model.ParamsContainer
|
|||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.txhistory.models.TxHistoryStateError
|
||||
|
|
@ -39,7 +39,7 @@ internal class TxHistoryModel @Inject constructor(
|
|||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase,
|
||||
private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
|
|
@ -165,7 +165,7 @@ internal class TxHistoryModel @Inject constructor(
|
|||
val userWallet: UserWallet = requireNotNull(getUserWalletUseCase(params.userWalletId).getOrNull()) {
|
||||
"User wallet not found"
|
||||
}
|
||||
getCurrencyStatusUpdatesUseCase(
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
|
||||
userWalletId = params.userWalletId,
|
||||
currencyId = params.currency.id,
|
||||
isSingleWalletWithTokens = userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.tangem.domain.nft.analytics.NFTAnalyticsEvent
|
|||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.settings.ShouldShowMarketsTooltipUseCase
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.TokensAction
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.TokenActionsState
|
||||
|
|
@ -67,7 +67,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
private val walletWarningsClickIntents: WalletWarningsClickIntentsImplementor,
|
||||
private val onrampStatusFactory: OnrampStatusFactory,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase,
|
||||
private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase,
|
||||
private val shouldShowMarketsTooltipUseCase: ShouldShowMarketsTooltipUseCase,
|
||||
|
|
@ -162,7 +162,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
|
||||
override fun onTransactionClick(txHash: String) {
|
||||
modelScope.launch(dispatchers.main) {
|
||||
val currency = getPrimaryCurrencyStatusUpdatesUseCase.unwrap(
|
||||
val currency = getSingleCryptoCurrencyStatusUseCase.unwrap(
|
||||
userWalletId = stateHolder.getSelectedWalletId(),
|
||||
)
|
||||
?.currency
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import com.tangem.domain.promo.GetStoryContentUseCase
|
|||
import com.tangem.domain.promo.models.StoryContentIds
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.IsCryptoCurrencyCoinCouldHideUseCase
|
||||
import com.tangem.domain.tokens.RemoveCurrencyUseCase
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
|
|
@ -110,7 +110,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val isCryptoCurrencyCoinCouldHide: IsCryptoCurrencyCoinCouldHideUseCase,
|
||||
private val removeCurrencyUseCase: RemoveCurrencyUseCase,
|
||||
private val getExploreUrlUseCase: GetExploreUrlUseCase,
|
||||
|
|
@ -489,7 +489,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
val userWalletId = stateHolder.getSelectedWalletId()
|
||||
|
||||
modelScope.launch(dispatchers.main) {
|
||||
val currencyStatus = getPrimaryCurrencyStatusUpdatesUseCase.unwrap(userWalletId) ?: return@launch
|
||||
val currencyStatus = getSingleCryptoCurrencyStatusUseCase.unwrap(userWalletId) ?: return@launch
|
||||
|
||||
when (val addresses = currencyStatus.value.networkAddress) {
|
||||
is NetworkAddress.Selectable -> {
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@ import com.tangem.domain.promo.ShouldShowPromoWalletUseCase
|
|||
import com.tangem.domain.promo.models.PromoId
|
||||
import com.tangem.domain.settings.NeverToSuggestRateAppUseCase
|
||||
import com.tangem.domain.settings.RemindToRateAppLaterUseCase
|
||||
import com.tangem.domain.tokens.FetchTokenListUseCase
|
||||
import com.tangem.domain.tokens.FetchTokenListUseCase.RefreshMode
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
|
||||
|
|
@ -91,7 +88,6 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
private val stateHolder: WalletStateController,
|
||||
private val walletEventSender: WalletEventSender,
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
private val fetchTokenListUseCase: FetchTokenListUseCase,
|
||||
private val setCardWasScannedUseCase: SetCardWasScannedUseCase,
|
||||
private val neverToSuggestRateAppUseCase: NeverToSuggestRateAppUseCase,
|
||||
private val remindToRateAppLaterUseCase: RemindToRateAppLaterUseCase,
|
||||
|
|
@ -105,7 +101,6 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||
private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val tokensFeatureToggles: TokensFeatureToggles,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
private val appRouter: AppRouter,
|
||||
) : BaseWalletClickIntents(), WalletWarningsClickIntents {
|
||||
|
|
@ -148,22 +143,13 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
).fold(
|
||||
ifLeft = { Timber.e(it, "Failed to derive public keys") },
|
||||
ifRight = {
|
||||
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
|
||||
multiNetworkStatusFetcher(
|
||||
params = MultiNetworkStatusFetcher.Params(
|
||||
userWalletId = userWallet.walletId,
|
||||
networks = missedAddressCurrencies.map(CryptoCurrency::network).toSet(),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
fetchTokenListUseCase(
|
||||
multiNetworkStatusFetcher(
|
||||
params = MultiNetworkStatusFetcher.Params(
|
||||
userWalletId = userWallet.walletId,
|
||||
mode = RefreshMode.SKIP_CURRENCIES,
|
||||
currencies = missedAddressCurrencies,
|
||||
).onLeft {
|
||||
Timber.e("Unable to refresh token list: $it")
|
||||
}
|
||||
}
|
||||
networks = missedAddressCurrencies.map(CryptoCurrency::network).toSet(),
|
||||
),
|
||||
)
|
||||
.onLeft { Timber.e("Unable to refresh token list: $it") }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import com.tangem.domain.common.util.cardTypesResolver
|
|||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.settings.IsReadyToShowRateAppUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -22,7 +22,7 @@ import javax.inject.Inject
|
|||
|
||||
@ModelScoped
|
||||
internal class GetSingleWalletWarningsFactory @Inject constructor(
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase,
|
||||
private val isNeedToBackupUseCase: IsNeedToBackupUseCase,
|
||||
|
|
@ -36,7 +36,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
|
|||
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
|
||||
|
||||
return combine(
|
||||
flow = getPrimaryCurrencyStatusUpdatesUseCase(userWallet.walletId),
|
||||
flow = getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWallet.walletId),
|
||||
flow2 = isReadyToShowRateAppUseCase().conflate(),
|
||||
flow3 = isNeedToBackupUseCase(userWallet.walletId).conflate(),
|
||||
flow4 = getWalletsUseCase().conflate(),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.domain
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -20,8 +20,8 @@ internal fun GetSelectedWalletSyncUseCase.unwrap(): UserWallet? {
|
|||
)
|
||||
}
|
||||
|
||||
internal suspend fun GetPrimaryCurrencyStatusUpdatesUseCase.unwrap(userWalletId: UserWalletId): CryptoCurrencyStatus? {
|
||||
return this(userWalletId)
|
||||
internal suspend fun GetSingleCryptoCurrencyStatusUseCase.unwrap(userWalletId: UserWalletId): CryptoCurrencyStatus? {
|
||||
return invokeSingleWallet(userWalletId)
|
||||
.conflate()
|
||||
.distinctUntilChanged()
|
||||
.filter(Either<CurrencyStatusError, CryptoCurrencyStatus>::isRight)
|
||||
|
|
@ -35,11 +35,11 @@ internal suspend fun GetPrimaryCurrencyStatusUpdatesUseCase.unwrap(userWalletId:
|
|||
)
|
||||
}
|
||||
|
||||
internal suspend fun GetPrimaryCurrencyStatusUpdatesUseCase.collectLatest(
|
||||
internal suspend fun GetSingleCryptoCurrencyStatusUseCase.collectLatest(
|
||||
userWalletId: UserWalletId,
|
||||
onRight: suspend (CryptoCurrencyStatus) -> Unit,
|
||||
) {
|
||||
this(userWalletId = userWalletId)
|
||||
invokeSingleWallet(userWalletId = userWalletId)
|
||||
.conflate()
|
||||
.distinctUntilChanged()
|
||||
.collectLatest { maybeStatus ->
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.domain.onramp.GetOnrampTransactionsUseCase
|
|||
import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase
|
||||
import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -29,7 +29,7 @@ internal class SingleWalletContentLoader(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val isRefresh: Boolean,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase,
|
||||
private val getSingleWalletWarningsFactory: GetSingleWalletWarningsFactory,
|
||||
private val setWalletWithFundsFoundUseCase: SetWalletWithFundsFoundUseCase,
|
||||
|
|
@ -48,7 +48,7 @@ internal class SingleWalletContentLoader(
|
|||
PrimaryCurrencySubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
setWalletWithFundsFoundUseCase = setWalletWithFundsFoundUseCase,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
|
|
@ -57,7 +57,7 @@ internal class SingleWalletContentLoader(
|
|||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
getCryptoCurrencyActionsUseCase = getCryptoCurrencyActionsUseCase,
|
||||
),
|
||||
SingleWalletNotificationsSubscriber(
|
||||
|
|
@ -78,7 +78,7 @@ internal class SingleWalletContentLoader(
|
|||
clickIntents = clickIntents,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
getOnrampTransactionsUseCase = getOnrampTransactionsUseCase,
|
||||
onrampRemoveTransactionUseCase = onrampRemoveTransactionUseCase,
|
||||
),
|
||||
|
|
@ -87,7 +87,7 @@ internal class SingleWalletContentLoader(
|
|||
isRefresh = isRefresh,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
txHistoryItemsCountUseCase = txHistoryItemsCountUseCase,
|
||||
txHistoryItemsUseCase = txHistoryItemsUseCase,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import com.tangem.domain.onramp.GetOnrampTransactionsUseCase
|
|||
import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase
|
||||
import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -22,7 +22,7 @@ import javax.inject.Inject
|
|||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletContentLoaderFactory @Inject constructor(
|
||||
private val stateHolder: WalletStateController,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase,
|
||||
private val getSingleWalletWarningsFactory: GetSingleWalletWarningsFactory,
|
||||
private val setWalletWithFundsFoundUseCase: SetWalletWithFundsFoundUseCase,
|
||||
|
|
@ -42,7 +42,7 @@ internal class SingleWalletContentLoaderFactory @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
isRefresh = isRefresh,
|
||||
stateHolder = stateHolder,
|
||||
getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
getCryptoCurrencyActionsUseCase = getCryptoCurrencyActionsUseCase,
|
||||
getSingleWalletWarningsFactory = getSingleWalletWarningsFactory,
|
||||
setWalletWithFundsFoundUseCase = setWalletWithFundsFoundUseCase,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.tangem.core.analytics.models.AnalyticsParam
|
|||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -23,7 +23,7 @@ import java.math.BigDecimal
|
|||
internal class PrimaryCurrencySubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val setWalletWithFundsFoundUseCase: SetWalletWithFundsFoundUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
|
|
@ -33,7 +33,7 @@ internal class PrimaryCurrencySubscriber(
|
|||
coroutineScope: CoroutineScope,
|
||||
): Flow<Pair<Either<CurrencyStatusError, CryptoCurrencyStatus>, AppCurrency>> {
|
||||
return combine(
|
||||
flow = getPrimaryCurrencyStatusUpdatesUseCase(userWallet.walletId)
|
||||
flow = getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWallet.walletId)
|
||||
.conflate()
|
||||
.distinctUntilChanged(),
|
||||
flow2 = getSelectedAppCurrencyUseCase()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.model.TokenActionsState
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
|
|
@ -15,13 +15,13 @@ internal class SingleWalletButtonsSubscriber(
|
|||
private val userWallet: UserWallet,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase,
|
||||
) : WalletSubscriber() {
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<TokenActionsState> {
|
||||
return channelFlow {
|
||||
getPrimaryCurrencyStatusUpdatesUseCase.collectLatest(userWalletId = userWallet.walletId) { status ->
|
||||
getSingleCryptoCurrencyStatusUseCase.collectLatest(userWalletId = userWallet.walletId) { status ->
|
||||
getCryptoCurrencyActionsUseCase(userWallet = userWallet, cryptoCurrencyStatus = status)
|
||||
.conflate()
|
||||
.distinctUntilChanged()
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency
|
|||
import com.tangem.domain.onramp.GetOnrampTransactionsUseCase
|
||||
import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase
|
||||
import com.tangem.domain.onramp.model.cache.OnrampTransaction
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -26,7 +26,7 @@ internal class SingleWalletExpressStatusesSubscriber(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getOnrampTransactionsUseCase: GetOnrampTransactionsUseCase,
|
||||
private val onrampRemoveTransactionUseCase: OnrampRemoveTransactionUseCase,
|
||||
) : WalletSubscriber() {
|
||||
|
|
@ -35,7 +35,7 @@ internal class SingleWalletExpressStatusesSubscriber(
|
|||
coroutineScope: CoroutineScope,
|
||||
): Flow<Pair<Either<CurrencyStatusError, CryptoCurrencyStatus>, AppCurrency>> {
|
||||
return combine(
|
||||
flow = getPrimaryCurrencyStatusUpdatesUseCase(userWalletId = userWallet.walletId)
|
||||
flow = getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWalletId = userWallet.walletId)
|
||||
.conflate()
|
||||
.distinctUntilChanged(),
|
||||
flow2 = getSelectedAppCurrencyUseCase()
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import androidx.paging.cachedIn
|
|||
import androidx.paging.map
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.domain.txhistory.models.TxHistoryListError
|
||||
|
|
@ -35,14 +35,14 @@ internal class TxHistorySubscriber(
|
|||
private val isRefresh: Boolean,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase,
|
||||
private val txHistoryItemsUseCase: GetTxHistoryItemsUseCase,
|
||||
) : WalletSubscriber() {
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<PagingData<TxHistoryItem>> {
|
||||
return flow {
|
||||
getPrimaryCurrencyStatusUpdatesUseCase.collectLatest(userWalletId = userWallet.walletId) { status ->
|
||||
getSingleCryptoCurrencyStatusUseCase.collectLatest(userWalletId = userWallet.walletId) { status ->
|
||||
val maybeTxHistoryItemCount = txHistoryItemsCountUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = status.currency,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ package com.tangem.features.walletconnect.components
|
|||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
interface WalletConnectEntryComponent : ComposableContentComponent {
|
||||
interface Factory : ComponentFactory<Unit, WalletConnectEntryComponent>
|
||||
data class Params(val userWalletId: UserWalletId)
|
||||
interface Factory : ComponentFactory<Params, WalletConnectEntryComponent>
|
||||
}
|
||||
|
|
@ -12,9 +12,8 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.features.wallet.api)
|
||||
implementation(projects.features.walletconnect.api)
|
||||
implementation(projects.domain.walletConnect)
|
||||
implementation(projects.domain.walletConnect.models)
|
||||
|
||||
/** Core */
|
||||
implementation(projects.core.configToggles)
|
||||
|
|
@ -24,13 +23,22 @@ dependencies {
|
|||
implementation(projects.common.ui)
|
||||
|
||||
/** Domain models */
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
implementation(projects.domain.balanceHiding.models)
|
||||
implementation(projects.domain.blockaid.models)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.qrScanning.models)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.walletConnect)
|
||||
implementation(projects.domain.walletConnect.models)
|
||||
|
||||
/** Domain */
|
||||
implementation(projects.domain.appCurrency)
|
||||
implementation(projects.domain.balanceHiding)
|
||||
implementation(projects.domain.qrScanning)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.wallets)
|
||||
|
||||
/** DI */
|
||||
implementation(deps.hilt.android)
|
||||
|
|
|
|||
|
|
@ -13,15 +13,17 @@ import com.tangem.core.decompose.context.childByContext
|
|||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.walletconnect.connections.model.WcConnectionsModel
|
||||
import com.tangem.features.walletconnect.connections.routes.WcConnectionsBottomSheetConfig
|
||||
import com.tangem.features.walletconnect.connections.ui.WcConnectionsContent
|
||||
|
||||
internal class ConnectionsComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
params: Params,
|
||||
) : AppComponentContext by appComponentContext, ComposableContentComponent {
|
||||
|
||||
private val model: WcConnectionsModel = getOrCreateModel()
|
||||
private val model: WcConnectionsModel = getOrCreateModel(params)
|
||||
private val bottomSheetSlot = childSlot(
|
||||
source = model.bottomSheetNavigation,
|
||||
serializer = null,
|
||||
|
|
@ -52,4 +54,6 @@ internal class ConnectionsComponent(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class Params(val userWalletId: UserWalletId)
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ import dagger.assisted.AssistedInject
|
|||
@Suppress("UnusedPrivateMember")
|
||||
internal class DefaultWalletConnectEntryComponent @AssistedInject constructor(
|
||||
@Assisted private val appComponentContext: AppComponentContext,
|
||||
@Assisted params: Unit,
|
||||
@Assisted private val params: WalletConnectEntryComponent.Params,
|
||||
) : AppComponentContext by appComponentContext, WalletConnectEntryComponent {
|
||||
|
||||
private val contentNavigation = StackNavigation<ConnectionsInnerRoute>()
|
||||
|
|
@ -47,12 +47,18 @@ internal class DefaultWalletConnectEntryComponent @AssistedInject constructor(
|
|||
config: ConnectionsInnerRoute,
|
||||
componentContext: ComponentContext,
|
||||
): ComposableContentComponent = when (config) {
|
||||
ConnectionsInnerRoute.Connections -> ConnectionsComponent(childByContext(componentContext))
|
||||
ConnectionsInnerRoute.Connections -> ConnectionsComponent(
|
||||
appComponentContext = childByContext(componentContext),
|
||||
params = ConnectionsComponent.Params(params.userWalletId),
|
||||
)
|
||||
ConnectionsInnerRoute.QrScan -> TODO("[REDACTED_JIRA]")
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : WalletConnectEntryComponent.Factory {
|
||||
override fun create(context: AppComponentContext, params: Unit): DefaultWalletConnectEntryComponent
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: WalletConnectEntryComponent.Params,
|
||||
): DefaultWalletConnectEntryComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
package com.tangem.features.walletconnect.connections.components
|
||||
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import com.arkivanov.decompose.extensions.compose.stack.Children
|
||||
import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation
|
||||
import com.arkivanov.decompose.extensions.compose.subscribeAsState
|
||||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.childStack
|
||||
import com.arkivanov.decompose.router.stack.pop
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
|
|
@ -18,8 +17,10 @@ import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
|
|||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.walletconnect.connections.model.WcAppInfoModel
|
||||
import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
|
|
@ -30,9 +31,8 @@ internal class WcAppInfoContainerComponent(
|
|||
) : AppComponentContext by appComponentContext, ComposableContentComponent {
|
||||
|
||||
private val model: WcAppInfoModel = getOrCreateModel(params = params)
|
||||
private val contentNavigation = StackNavigation<WcAppInfoRoutes>()
|
||||
private val contentStack = childStack(
|
||||
source = contentNavigation,
|
||||
source = model.contentNavigation,
|
||||
serializer = WcAppInfoRoutes.serializer(),
|
||||
initialConfiguration = WcAppInfoRoutes.AppInfo,
|
||||
childFactory = ::screenChild,
|
||||
|
|
@ -51,10 +51,17 @@ internal class WcAppInfoContainerComponent(
|
|||
onDismissRequest = ::dismiss,
|
||||
content = content.active.configuration,
|
||||
),
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
onBack = ::contentBack,
|
||||
containerColor = when (content.active.configuration) {
|
||||
is WcAppInfoRoutes.Alert,
|
||||
is WcAppInfoRoutes.SelectNetworks,
|
||||
is WcAppInfoRoutes.AppInfo,
|
||||
-> TangemTheme.colors.background.tertiary
|
||||
is WcAppInfoRoutes.SelectWallet -> TangemTheme.colors.background.primary
|
||||
},
|
||||
title = { config -> Title(route = config) },
|
||||
content = {
|
||||
Children(stack = content, animation = stackAnimation()) { child ->
|
||||
Children(modifier = Modifier.animateContentSize(), stack = content) { child ->
|
||||
child.instance.Content(modifier = Modifier)
|
||||
}
|
||||
},
|
||||
|
|
@ -64,7 +71,12 @@ internal class WcAppInfoContainerComponent(
|
|||
@Composable
|
||||
private fun Title(route: WcAppInfoRoutes) {
|
||||
TangemModalBottomSheetTitle(
|
||||
title = resourceReference(R.string.wc_wallet_connect),
|
||||
title = when (route) {
|
||||
is WcAppInfoRoutes.Alert -> null
|
||||
WcAppInfoRoutes.AppInfo -> resourceReference(R.string.wc_wallet_connect)
|
||||
WcAppInfoRoutes.SelectNetworks -> TODO("[REDACTED_TASK_KEY]")
|
||||
WcAppInfoRoutes.SelectWallet -> stringReference("Choose wallet")
|
||||
},
|
||||
startIconRes = when (route) {
|
||||
is WcAppInfoRoutes.AppInfo, is WcAppInfoRoutes.Alert -> null
|
||||
is WcAppInfoRoutes.SelectNetworks, is WcAppInfoRoutes.SelectWallet -> R.drawable.ic_back_24
|
||||
|
|
@ -88,19 +100,25 @@ internal class WcAppInfoContainerComponent(
|
|||
}
|
||||
|
||||
private fun contentBack() {
|
||||
contentNavigation.pop()
|
||||
if (contentStack.value.active.configuration == WcAppInfoRoutes.AppInfo) {
|
||||
dismiss()
|
||||
} else {
|
||||
model.contentNavigation.pop()
|
||||
}
|
||||
}
|
||||
|
||||
private fun screenChild(config: WcAppInfoRoutes, componentContext: ComponentContext): ComposableContentComponent =
|
||||
when (config) {
|
||||
is WcAppInfoRoutes.AppInfo -> WcAppInfoComponent(
|
||||
appComponentContext = childByContext(componentContext),
|
||||
model = model,
|
||||
)
|
||||
private fun screenChild(config: WcAppInfoRoutes, componentContext: ComponentContext): ComposableContentComponent {
|
||||
val appComponentContext = childByContext(componentContext)
|
||||
return when (config) {
|
||||
is WcAppInfoRoutes.AppInfo -> WcAppInfoComponent(appComponentContext = appComponentContext, model = model)
|
||||
is WcAppInfoRoutes.Alert -> TODO()
|
||||
WcAppInfoRoutes.SelectNetworks -> TODO()
|
||||
WcAppInfoRoutes.SelectWallet -> TODO()
|
||||
WcAppInfoRoutes.SelectWallet -> WcSelectWalletComponent(
|
||||
appComponentContext = appComponentContext,
|
||||
model = model,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class Params(val wcUrl: String, val source: WcPairRequest.Source)
|
||||
data class Params(val userWalletId: UserWalletId, val wcUrl: String, val source: WcPairRequest.Source)
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
package com.tangem.features.walletconnect.connections.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
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.ui.components.block.TangemBlockCardColors
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.walletconnect.connections.model.WcAppInfoModel
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal class WcSelectWalletComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
private val model: WcAppInfoModel,
|
||||
) : AppComponentContext by appComponentContext, ComposableContentComponent {
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val walletsState by model.walletsUiState.collectAsStateWithLifecycle()
|
||||
WcSelectWalletContent(
|
||||
modifier = modifier.padding(start = 16.dp, end = 16.dp, bottom = 16.dp),
|
||||
wallets = walletsState.wallets,
|
||||
selectedWalletId = walletsState.selectedUserWallet.walletId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WcSelectWalletContent(
|
||||
wallets: ImmutableList<UserWalletItemUM>,
|
||||
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) {
|
||||
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,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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() {
|
||||
TangemThemePreview {
|
||||
WcSelectWalletContent(
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors.background.tertiary)
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp),
|
||||
selectedWalletId = UserWalletId("user_wallet_1".encodeToByteArray()),
|
||||
wallets = persistentListOf(
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_1".encodeToByteArray()),
|
||||
name = stringReference("Tangem 2.0"),
|
||||
information = stringReference("42 tokens"),
|
||||
balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false),
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_2".encodeToByteArray()),
|
||||
name = stringReference("Tangem White"),
|
||||
information = stringReference("24 tokens"),
|
||||
balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false),
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_3".encodeToByteArray()),
|
||||
name = stringReference("Bitcoin"),
|
||||
information = stringReference("1 token"),
|
||||
balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false),
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_4".encodeToByteArray()),
|
||||
name = stringReference("Tangem 1.0"),
|
||||
information = stringReference("21 tokens"),
|
||||
balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false),
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ internal sealed class WcAppInfoUM : TangemBottomSheetConfigContent {
|
|||
val appSubtitle: String,
|
||||
val notification: WcAppInfoSecurityNotification?,
|
||||
val walletName: String,
|
||||
val onWalletClick: () -> Unit,
|
||||
val networksInfo: WcNetworksInfo,
|
||||
override val connectButtonConfig: WcPrimaryButtonConfig,
|
||||
override val onDismiss: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.features.walletconnect.connections.entity
|
||||
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
internal data class WcAppInfoWalletUM(
|
||||
val wallets: ImmutableList<UserWalletItemUM>,
|
||||
val selectedUserWallet: UserWallet,
|
||||
)
|
||||
|
|
@ -1,47 +1,98 @@
|
|||
package com.tangem.features.walletconnect.connections.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.pop
|
||||
import com.arkivanov.decompose.router.stack.pushNew
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
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.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.tokens.GetWalletTotalBalanceUseCase
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.walletconnect.model.WcSessionApprove
|
||||
import com.tangem.domain.walletconnect.model.WcSessionProposal
|
||||
import com.tangem.domain.walletconnect.usecase.pair.WcPairState
|
||||
import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.features.walletconnect.connections.components.WcAppInfoContainerComponent
|
||||
import com.tangem.features.walletconnect.connections.entity.WcAppInfoUM
|
||||
import com.tangem.features.walletconnect.connections.entity.WcAppInfoWalletUM
|
||||
import com.tangem.features.walletconnect.connections.entity.WcPrimaryButtonConfig
|
||||
import com.tangem.features.walletconnect.connections.model.transformers.WcAppInfoTransformer
|
||||
import com.tangem.features.walletconnect.connections.model.transformers.WcAppInfoWalletChangedTransformer
|
||||
import com.tangem.features.walletconnect.connections.model.transformers.WcConnectButtonProgressTransformer
|
||||
import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes
|
||||
import com.tangem.features.walletconnect.connections.utils.WcUserWalletsFetcher
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.flow.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.properties.Delegates
|
||||
import com.tangem.utils.transformer.update as transformerUpdate
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Stable
|
||||
@ModelScoped
|
||||
internal class WcAppInfoModel @Inject constructor(
|
||||
private val router: Router,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
wcPairUseCaseFactory: WcPairUseCase.Factory,
|
||||
private val router: Router,
|
||||
getWalletsUseCase: GetWalletsUseCase,
|
||||
getWalletTotalBalanceUseCase: GetWalletTotalBalanceUseCase,
|
||||
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
messageSender: UiMessageSender,
|
||||
getCardImageUseCase: GetCardImageUseCase,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
||||
private val params: WcAppInfoContainerComponent.Params = paramsContainer.require()
|
||||
private val wcPairUseCase = wcPairUseCaseFactory.create(WcPairRequest(uri = params.wcUrl, source = params.source))
|
||||
private val wcPairUseCase = wcPairUseCaseFactory.create(
|
||||
WcPairRequest(
|
||||
userWalletId = params.userWalletId,
|
||||
uri = params.wcUrl,
|
||||
source = params.source,
|
||||
),
|
||||
)
|
||||
private val userWalletsFetcher = WcUserWalletsFetcher(
|
||||
getWalletsUseCase = getWalletsUseCase,
|
||||
getWalletTotalBalanceUseCase = getWalletTotalBalanceUseCase,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
getBalanceHidingSettingsUseCase = getBalanceHidingSettingsUseCase,
|
||||
messageSender = messageSender,
|
||||
getCardImageUseCase = getCardImageUseCase,
|
||||
onWalletSelected = ::onWalletSelected,
|
||||
)
|
||||
|
||||
private val selectedUserWalletFlow =
|
||||
MutableStateFlow(getWalletsUseCase.invokeSync().first { it.walletId == params.userWalletId })
|
||||
// TODO(wc) Doston: Temp solution, will be fixed in next PR`s
|
||||
private var proposalNetwork by Delegates.notNull<WcSessionProposal.ProposalNetwork>()
|
||||
internal var sessionProposal by Delegates.notNull<WcSessionProposal>()
|
||||
|
||||
// UI states
|
||||
internal val contentNavigation = StackNavigation<WcAppInfoRoutes>()
|
||||
val appInfoUiState: StateFlow<WcAppInfoUM>
|
||||
field = MutableStateFlow<WcAppInfoUM>(createLoadingState())
|
||||
|
||||
// TODO(wc) Doston: Temp solution, will be fixed in next PR`s
|
||||
private var userWallet by Delegates.notNull<UserWallet>()
|
||||
private var proposalNetwork by Delegates.notNull<WcSessionProposal.ProposalNetwork>()
|
||||
val walletsUiState: StateFlow<WcAppInfoWalletUM>
|
||||
field = MutableStateFlow(WcAppInfoWalletUM(persistentListOf(), selectedUserWalletFlow.value))
|
||||
|
||||
init {
|
||||
loadDAppInfo()
|
||||
combine(
|
||||
flow = userWalletsFetcher.userWallets,
|
||||
flow2 = selectedUserWalletFlow,
|
||||
transform = ::updateWalletsState,
|
||||
).launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun loadDAppInfo() {
|
||||
|
|
@ -62,14 +113,15 @@ internal class WcAppInfoModel @Inject constructor(
|
|||
}
|
||||
is WcPairState.Loading -> appInfoUiState.update { createLoadingState() }
|
||||
is WcPairState.Proposal -> {
|
||||
userWallet = state.dAppSession.proposalNetwork.keys.first { !it.isLocked }
|
||||
proposalNetwork = state.dAppSession.proposalNetwork.getValue(userWallet)
|
||||
sessionProposal = state.dAppSession
|
||||
proposalNetwork = sessionProposal.proposalNetwork.getValue(selectedUserWalletFlow.value)
|
||||
appInfoUiState.transformerUpdate(
|
||||
WcAppInfoTransformer(
|
||||
dAppSession = state.dAppSession,
|
||||
onDismiss = ::dismiss,
|
||||
onConnect = ::onConnect,
|
||||
userWallet = userWallet,
|
||||
onWalletClick = { contentNavigation.pushNew(WcAppInfoRoutes.SelectWallet) },
|
||||
userWallet = selectedUserWalletFlow.value,
|
||||
proposalNetwork = proposalNetwork,
|
||||
),
|
||||
)
|
||||
|
|
@ -87,13 +139,24 @@ internal class WcAppInfoModel @Inject constructor(
|
|||
private fun onConnect() {
|
||||
wcPairUseCase.approve(
|
||||
WcSessionApprove(
|
||||
wallet = userWallet,
|
||||
network =
|
||||
proposalNetwork.required.plus(proposalNetwork.available).toList(),
|
||||
wallet = selectedUserWalletFlow.value,
|
||||
network = proposalNetwork.required.plus(proposalNetwork.available).toList(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun onWalletSelected(userWalletId: UserWalletId) {
|
||||
val selectedUserWallet = sessionProposal.proposalNetwork.keys.first { it.walletId == userWalletId }
|
||||
selectedUserWalletFlow.update { selectedUserWallet }
|
||||
proposalNetwork = sessionProposal.proposalNetwork.getValue(selectedUserWallet)
|
||||
appInfoUiState.transformerUpdate(WcAppInfoWalletChangedTransformer(selectedUserWallet, proposalNetwork))
|
||||
contentNavigation.pop()
|
||||
}
|
||||
|
||||
private fun updateWalletsState(items: ImmutableList<UserWalletItemUM>, userWallet: UserWallet) {
|
||||
walletsUiState.update { state -> state.copy(wallets = items, selectedUserWallet = userWallet) }
|
||||
}
|
||||
|
||||
private fun createLoadingState(): WcAppInfoUM.Loading {
|
||||
return WcAppInfoUM.Loading(
|
||||
onDismiss = ::dismiss,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ 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.iconResId
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
|
|
@ -13,9 +14,10 @@ import com.tangem.domain.walletconnect.usecase.WcSessionsUseCase
|
|||
import com.tangem.domain.walletconnect.usecase.disconnect.WcDisconnectUseCase
|
||||
import com.tangem.features.walletconnect.connections.components.WcConnectedAppInfoComponent
|
||||
import com.tangem.features.walletconnect.connections.entity.WcConnectedAppInfoUM
|
||||
import com.tangem.features.walletconnect.connections.entity.WcNetworkInfoItem
|
||||
import com.tangem.features.walletconnect.connections.entity.WcPrimaryButtonConfig
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
|
@ -56,7 +58,15 @@ internal class WcConnectedAppInfoModel @Inject constructor(
|
|||
isVerified = session.securityStatus == CheckDAppResult.SAFE,
|
||||
appSubtitle = session.sdkModel.appMetaData.description,
|
||||
walletName = session.wallet.name,
|
||||
networks = persistentListOf(), // TODO(wc): Nikolai & Doston: Where to find networks???
|
||||
networks = session.networks
|
||||
.map {
|
||||
WcNetworkInfoItem(
|
||||
id = it.id.value,
|
||||
icon = it.iconResId,
|
||||
name = it.name,
|
||||
symbol = it.currencySymbol,
|
||||
)
|
||||
}.toImmutableList(),
|
||||
disconnectButtonConfig = WcPrimaryButtonConfig(
|
||||
showProgress = false,
|
||||
enabled = true,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.arkivanov.decompose.router.slot.activate
|
|||
import com.tangem.common.routing.AppRoute
|
||||
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.components.appbar.models.TopAppBarButtonUM
|
||||
|
|
@ -16,11 +17,12 @@ import com.tangem.core.ui.message.EventMessageAction
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.WcPairService
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.usecase.WcSessionsUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.disconnect.WcDisconnectUseCase
|
||||
import com.tangem.features.walletconnect.connections.components.ConnectionsComponent
|
||||
import com.tangem.features.walletconnect.connections.entity.WcConnectionsState
|
||||
import com.tangem.features.walletconnect.connections.entity.WcConnectionsTopAppBarConfig
|
||||
import com.tangem.features.walletconnect.connections.model.transformers.WcSessionsTransformer
|
||||
|
|
@ -44,8 +46,10 @@ internal class WcConnectionsModel @Inject constructor(
|
|||
private val wcDisconnectUseCase: WcDisconnectUseCase,
|
||||
private val wcPairService: WcPairService,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<ConnectionsComponent.Params>()
|
||||
val uiState: StateFlow<WcConnectionsState>
|
||||
field = MutableStateFlow<WcConnectionsState>(getInitialState())
|
||||
val bottomSheetNavigation: SlotNavigation<WcConnectionsBottomSheetConfig> = SlotNavigation()
|
||||
|
|
@ -58,7 +62,15 @@ internal class WcConnectionsModel @Inject constructor(
|
|||
private fun listenQrUpdates() {
|
||||
listenToQrScanningUseCase(SourceType.WALLET_CONNECT)
|
||||
.getOrElse { emptyFlow() }
|
||||
.onEach { wcUrl -> wcPairService.pair(WcPairRequest(wcUrl, WcPairRequest.Source.QR)) }
|
||||
.onEach { wcUrl ->
|
||||
wcPairService.pair(
|
||||
WcPairRequest(
|
||||
userWalletId = params.userWalletId,
|
||||
uri = wcUrl,
|
||||
source = WcPairRequest.Source.QR,
|
||||
),
|
||||
)
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
package com.tangem.features.walletconnect.connections.model.transformers
|
||||
|
||||
import com.domain.blockaid.models.dapp.CheckDAppResult
|
||||
import com.tangem.core.ui.extensions.iconResId
|
||||
import com.tangem.domain.walletconnect.model.WcSessionProposal
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.walletconnect.connections.entity.*
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal class WcAppInfoTransformer(
|
||||
private val dAppSession: WcSessionProposal,
|
||||
private val onDismiss: () -> Unit,
|
||||
private val onConnect: () -> Unit,
|
||||
private val onWalletClick: () -> Unit,
|
||||
private val userWallet: UserWallet,
|
||||
private val proposalNetwork: WcSessionProposal.ProposalNetwork,
|
||||
) : Transformer<WcAppInfoUM> {
|
||||
|
|
@ -24,7 +23,8 @@ internal class WcAppInfoTransformer(
|
|||
appSubtitle = dAppSession.dAppMetaData.description,
|
||||
notification = createNotification(dAppSession.securityStatus),
|
||||
walletName = userWallet.name,
|
||||
networksInfo = convertNetworksInfo(proposalNetwork),
|
||||
onWalletClick = onWalletClick,
|
||||
networksInfo = WcNetworksInfoConverter.convert(proposalNetwork),
|
||||
connectButtonConfig = WcPrimaryButtonConfig(
|
||||
showProgress = false,
|
||||
enabled = proposalNetwork.missingRequired.isEmpty(),
|
||||
|
|
@ -41,26 +41,4 @@ internal class WcAppInfoTransformer(
|
|||
CheckDAppResult.FAILED_TO_VERIFY -> WcAppInfoSecurityNotification.UnknownDomain
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertNetworksInfo(proposalNetwork: WcSessionProposal.ProposalNetwork): WcNetworksInfo {
|
||||
return if (proposalNetwork.missingRequired.isNotEmpty()) {
|
||||
WcNetworksInfo.MissingRequiredNetworkInfo(
|
||||
networks = proposalNetwork.missingRequired
|
||||
.joinToString { it.name },
|
||||
)
|
||||
} else {
|
||||
WcNetworksInfo.ContainsAllRequiredNetworks(
|
||||
items = (proposalNetwork.required + proposalNetwork.available)
|
||||
.map {
|
||||
WcNetworkInfoItem(
|
||||
id = it.id.value,
|
||||
icon = it.iconResId,
|
||||
name = it.name,
|
||||
symbol = it.currencySymbol,
|
||||
)
|
||||
}
|
||||
.toImmutableList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.features.walletconnect.connections.model.transformers
|
||||
|
||||
import com.tangem.domain.walletconnect.model.WcSessionProposal
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
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,
|
||||
) : Transformer<WcAppInfoUM> {
|
||||
override fun transform(prevState: WcAppInfoUM): WcAppInfoUM {
|
||||
val contentState = prevState as? WcAppInfoUM.Content ?: return prevState
|
||||
return contentState.copy(
|
||||
walletName = selectedUserWallet.name,
|
||||
networksInfo = WcNetworksInfoConverter.convert(proposalNetwork),
|
||||
connectButtonConfig = prevState.connectButtonConfig.copy(
|
||||
enabled = proposalNetwork.missingRequired.isEmpty(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.tangem.features.walletconnect.connections.model.transformers
|
||||
|
||||
import com.tangem.core.ui.extensions.iconResId
|
||||
import com.tangem.domain.walletconnect.model.WcSessionProposal
|
||||
import com.tangem.features.walletconnect.connections.entity.WcNetworkInfoItem
|
||||
import com.tangem.features.walletconnect.connections.entity.WcNetworksInfo
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal object WcNetworksInfoConverter : Converter<WcSessionProposal.ProposalNetwork, WcNetworksInfo> {
|
||||
override fun convert(value: WcSessionProposal.ProposalNetwork): WcNetworksInfo {
|
||||
return if (value.missingRequired.isNotEmpty()) {
|
||||
WcNetworksInfo.MissingRequiredNetworkInfo(
|
||||
networks = value.missingRequired
|
||||
.joinToString { it.name },
|
||||
)
|
||||
} else {
|
||||
WcNetworksInfo.ContainsAllRequiredNetworks(
|
||||
items = (value.required + value.available)
|
||||
.map {
|
||||
WcNetworkInfoItem(
|
||||
id = it.id.value,
|
||||
icon = it.iconResId,
|
||||
name = it.name,
|
||||
symbol = it.currencySymbol,
|
||||
)
|
||||
}
|
||||
.toImmutableList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ import com.tangem.core.decompose.model.getOrCreateModel
|
|||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.features.walletconnect.components.WcRoutingComponent
|
||||
import com.tangem.features.walletconnect.connections.components.WcAppInfoContainerComponent
|
||||
import com.tangem.features.walletconnect.transaction.components.WcSignTransactionComponent
|
||||
import com.tangem.features.walletconnect.transaction.components.WcSignTransactionContainerComponent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -55,13 +55,17 @@ internal class DefaultWcRoutingComponent @AssistedInject constructor(
|
|||
router = model.innerRouter,
|
||||
)
|
||||
return when (config) {
|
||||
is WcInnerRoute.SignMessage -> WcSignTransactionComponent(
|
||||
is WcInnerRoute.SignMessage -> WcSignTransactionContainerComponent(
|
||||
childContext,
|
||||
params = WcSignTransactionComponent.Params(config.rawRequest),
|
||||
params = WcSignTransactionContainerComponent.Params(config.rawRequest),
|
||||
)
|
||||
is WcInnerRoute.Pair -> WcAppInfoContainerComponent(
|
||||
childContext,
|
||||
WcAppInfoContainerComponent.Params(config.request.uri, config.request.source),
|
||||
WcAppInfoContainerComponent.Params(
|
||||
userWalletId = config.request.userWalletId,
|
||||
wcUrl = config.request.uri,
|
||||
source = config.request.source,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,7 +220,12 @@ private fun WcAppInfoSecondBlock(state: WcAppInfoUM.Content, modifier: Modifier
|
|||
val itemsModifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(TangemTheme.dimens.spacing12)
|
||||
WalletRowItem(modifier = itemsModifier, walletName = state.walletName)
|
||||
WalletRowItem(
|
||||
modifier = Modifier
|
||||
.clickable(onClick = state.onWalletClick)
|
||||
.then(itemsModifier),
|
||||
walletName = state.walletName,
|
||||
)
|
||||
HorizontalDivider(thickness = 1.dp, color = TangemTheme.colors.stroke.primary)
|
||||
SelectNetworksBlock(
|
||||
networksInfo = state.networksInfo,
|
||||
|
|
@ -565,6 +570,7 @@ private class WcAppInfoStateProvider : CollectionPreviewParameterProvider<WcAppI
|
|||
appSubtitle = "react-app.walletconnect.com",
|
||||
notification = WcAppInfoSecurityNotification.SecurityRisk,
|
||||
walletName = "Tangem 2.0",
|
||||
onWalletClick = {},
|
||||
networksInfo = WcNetworksInfo.ContainsAllRequiredNetworks(
|
||||
items = persistentListOf(
|
||||
WcNetworkInfoItem(
|
||||
|
|
@ -604,6 +610,7 @@ private class WcAppInfoStateProvider : CollectionPreviewParameterProvider<WcAppI
|
|||
appSubtitle = "react-app.walletconnect.com",
|
||||
notification = WcAppInfoSecurityNotification.UnknownDomain,
|
||||
walletName = "Tangem 2.0",
|
||||
onWalletClick = {},
|
||||
networksInfo = WcNetworksInfo.MissingRequiredNetworkInfo(networks = "Solana"),
|
||||
onDismiss = {},
|
||||
connectButtonConfig = WcPrimaryButtonConfig(showProgress = false, enabled = true, onClick = {}),
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue