Updated on 2026-08-14

This commit is contained in:
Tangem 2025-08-01 16:19:01 +05:00
parent bcc6331bb8
commit 816d8532de
5 changed files with 49 additions and 34 deletions

View file

@ -10,19 +10,21 @@ import com.tangem.domain.express.ExpressRepository
import com.tangem.domain.express.models.ExpressProvider import com.tangem.domain.express.models.ExpressProvider
import com.tangem.domain.express.models.ExpressProviderType import com.tangem.domain.express.models.ExpressProviderType
import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWallet
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.extensions.filterIf import com.tangem.utils.extensions.filterIf
import timber.log.Timber import timber.log.Timber
internal class DefaultExpressRepository( internal class DefaultExpressRepository(
private val tangemExpressApi: TangemExpressApi, private val tangemExpressApi: TangemExpressApi,
private val appPreferencesStore: AppPreferencesStore, private val appPreferencesStore: AppPreferencesStore,
private val dispatchers: CoroutineDispatcherProvider,
) : ExpressRepository { ) : ExpressRepository {
override suspend fun getProviders( override suspend fun getProviders(
userWallet: UserWallet, userWallet: UserWallet,
filterProviderTypes: List<ExpressProviderType>, filterProviderTypes: List<ExpressProviderType>,
): List<ExpressProvider> { ): List<ExpressProvider> = with(dispatchers.io) {
return safeApiCall( safeApiCall(
call = { call = {
tangemExpressApi.getProviders( tangemExpressApi.getProviders(
userWalletId = userWallet.walletId.stringValue, userWalletId = userWallet.walletId.stringValue,

View file

@ -10,6 +10,7 @@ import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.domain.express.ExpressErrorResolver import com.tangem.domain.express.ExpressErrorResolver
import com.tangem.domain.express.ExpressRepository import com.tangem.domain.express.ExpressRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
@ -34,10 +35,12 @@ internal object ExpressDataModule {
fun provideExpressRepository( fun provideExpressRepository(
tangemExpressApi: TangemExpressApi, tangemExpressApi: TangemExpressApi,
appPreferencesStore: AppPreferencesStore, appPreferencesStore: AppPreferencesStore,
dispatchers: CoroutineDispatcherProvider,
): ExpressRepository { ): ExpressRepository {
return DefaultExpressRepository( return DefaultExpressRepository(
tangemExpressApi = tangemExpressApi, tangemExpressApi = tangemExpressApi,
appPreferencesStore = appPreferencesStore, appPreferencesStore = appPreferencesStore,
dispatchers = dispatchers,
) )
} }
} }

View file

@ -7,10 +7,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.mapNotNull
/** /**
* Default implementation of [SingleQuoteStatusProducer] * Default implementation of [SingleQuoteStatusProducer]
@ -28,7 +25,7 @@ internal class DefaultSingleQuoteStatusProducer @AssistedInject constructor(
override fun produce(): Flow<QuoteStatus> { override fun produce(): Flow<QuoteStatus> {
return quotesStatusesStore.get() return quotesStatusesStore.get()
.mapNotNull { quotes -> quotes.firstOrNull { it.rawCurrencyId == params.rawCurrencyId } } .mapNotNull { quotes -> quotes.firstOrNull { it.rawCurrencyId == params.rawCurrencyId } ?: fallback }
.distinctUntilChanged() .distinctUntilChanged()
.flowOn(dispatchers.default) .flowOn(dispatchers.default)
} }

View file

@ -24,6 +24,7 @@ import com.tangem.domain.express.models.ExpressRateType
import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.NetworkStatus import com.tangem.domain.models.network.NetworkStatus
import com.tangem.domain.models.quote.QuoteStatus
import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
@ -65,7 +66,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
initialCurrency: CryptoCurrency, initialCurrency: CryptoCurrency,
cryptoCurrencyStatusList: List<CryptoCurrencyStatus>, cryptoCurrencyStatusList: List<CryptoCurrencyStatus>,
filterProviderTypes: List<ExpressProviderType>, filterProviderTypes: List<ExpressProviderType>,
): List<SwapPairModel> = withContext(coroutineDispatcher.io) { ): List<SwapPairModel> = withContext(coroutineDispatcher.default) {
val cryptoCurrencyList = cryptoCurrencyStatusList.map { it.currency } val cryptoCurrencyList = cryptoCurrencyStatusList.map { it.currency }
val allPairs = getPairsInternal( val allPairs = getPairsInternal(
@ -113,7 +114,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
initialCurrency: CryptoCurrency, initialCurrency: CryptoCurrency,
cryptoCurrencyList: List<CryptoCurrency>, cryptoCurrencyList: List<CryptoCurrency>,
filterProviderTypes: List<ExpressProviderType>, filterProviderTypes: List<ExpressProviderType>,
): List<SwapPairModel> = withContext(coroutineDispatcher.io) { ): List<SwapPairModel> = withContext(coroutineDispatcher.default) {
val allPairs = getPairsInternal( val allPairs = getPairsInternal(
userWallet = userWallet, userWallet = userWallet,
initialCurrency = initialCurrency, initialCurrency = initialCurrency,
@ -330,25 +331,27 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
userWallet: UserWallet, userWallet: UserWallet,
from: List<CryptoCurrency>, from: List<CryptoCurrency>,
to: List<CryptoCurrency>, to: List<CryptoCurrency>,
) = safeApiCall( ) = withContext(coroutineDispatcher.io) {
call = { safeApiCall(
tangemExpressApi.getPairs( call = {
userWalletId = userWallet.walletId.stringValue, tangemExpressApi.getPairs(
refCode = ExpressUtils.getRefCode( userWalletId = userWallet.walletId.stringValue,
userWallet = userWallet, refCode = ExpressUtils.getRefCode(
appPreferencesStore = appPreferencesStore, userWallet = userWallet,
), appPreferencesStore = appPreferencesStore,
body = PairsRequestBody( ),
from = tokenInfoConverter.convertList(from), body = PairsRequestBody(
to = tokenInfoConverter.convertList(to), from = tokenInfoConverter.convertList(from),
), to = tokenInfoConverter.convertList(to),
).getOrThrow() ),
}, ).getOrThrow()
onError = { },
Timber.w(it, "Unable to get pairs") onError = {
throw it Timber.w(it, "Unable to get pairs")
}, throw it
) },
)
}
/** /**
* Send with swap specific currency status creation * Send with swap specific currency status creation
@ -360,9 +363,9 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
val quote = singleQuoteStatusSupplier.getSyncOrNull( val quote = singleQuoteStatusSupplier.getSyncOrNull(
params = SingleQuoteStatusProducer.Params(rawCurrencyId = rawCurrencyId), params = SingleQuoteStatusProducer.Params(rawCurrencyId = rawCurrencyId),
)?.right() )
if (quote == null) { if (quote == null || quote.value is QuoteStatus.Empty) {
singleQuoteStatusFetcher.invoke( singleQuoteStatusFetcher.invoke(
params = SingleQuoteStatusFetcher.Params( params = SingleQuoteStatusFetcher.Params(
rawCurrencyId = rawCurrencyId, rawCurrencyId = rawCurrencyId,
@ -373,7 +376,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
return currencyStatusProxyCreator.createCurrencyStatus( return currencyStatusProxyCreator.createCurrencyStatus(
currency = cryptoCurrency, currency = cryptoCurrency,
maybeQuoteStatus = quote ?: singleQuoteStatusSupplier.getSyncOrNull( maybeQuoteStatus = quote?.right() ?: singleQuoteStatusSupplier.getSyncOrNull(
params = SingleQuoteStatusProducer.Params(rawCurrencyId = rawCurrencyId), params = SingleQuoteStatusProducer.Params(rawCurrencyId = rawCurrencyId),
).right(), ).right(),
maybeNetworkStatus = NetworkStatus( maybeNetworkStatus = NetworkStatus(

View file

@ -24,12 +24,13 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastForEachIndexed
import com.tangem.core.ui.components.SpacerWMax import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.message.* import com.tangem.core.ui.components.bottomsheets.message.*
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
import com.tangem.core.ui.extensions.* import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.res.TangemThemePreview
@ -94,13 +95,22 @@ internal fun SwapChooseTokenNetworkContent(state: SwapChooseTokenNetworkContentU
@Composable @Composable
private fun SwapChooseTokenNetworkContentList(swapNetworks: ImmutableList<SwapChooseNetworkUM>) { private fun SwapChooseTokenNetworkContentList(swapNetworks: ImmutableList<SwapChooseNetworkUM>) {
Column { Column(
swapNetworks.fastForEach { network -> modifier = Modifier
.padding(top = 8.dp)
.padding(16.dp),
) {
swapNetworks.fastForEachIndexed { index, network ->
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(6.dp), horizontalArrangement = Arrangement.spacedBy(6.dp),
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.roundedShapeItemDecoration(
currentIndex = index,
lastIndex = swapNetworks.lastIndex,
addDefaultPadding = false,
)
.clickable( .clickable(
interactionSource = remember { MutableInteractionSource() }, interactionSource = remember { MutableInteractionSource() },
indication = ripple(), indication = ripple(),