Updated on 2026-08-14

This commit is contained in:
Tangem 2024-11-21 12:09:33 +03:00
commit 85423227c4
390 changed files with 11140 additions and 1722 deletions

View file

@ -19,6 +19,7 @@ dependencies {
implementation(projects.domain.tokens.models)
implementation(projects.domain.txhistory.models)
implementation(projects.domain.wallets.models)
implementation(projects.domain.staking.models)
/** Project - Data */
implementation(projects.core.datasource)

View file

@ -2,12 +2,11 @@ package com.tangem.data.tokens.di
import com.tangem.data.common.cache.CacheRegistry
import com.tangem.data.tokens.repository.*
import com.tangem.datasource.api.express.TangemExpressApi
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.exchangeservice.swap.SwapServiceLoader
import com.tangem.datasource.local.network.NetworksStatusesStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.quote.QuotesStore
import com.tangem.datasource.local.token.ExpressAssetsStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.tokens.repository.*
import com.tangem.domain.walletmanager.WalletManagersFacade
@ -26,23 +25,21 @@ internal object TokensDataModule {
@Singleton
fun provideCurrenciesRepository(
tangemTechApi: TangemTechApi,
tangemExpressApi: TangemExpressApi,
appPreferencesStore: AppPreferencesStore,
userWalletsStore: UserWalletsStore,
walletManagersFacade: WalletManagersFacade,
expressAssetsStore: ExpressAssetsStore,
cacheRegistry: CacheRegistry,
dispatchers: CoroutineDispatcherProvider,
swapServiceLoader: SwapServiceLoader,
): CurrenciesRepository {
return DefaultCurrenciesRepository(
tangemTechApi = tangemTechApi,
tangemExpressApi = tangemExpressApi,
appPreferencesStore = appPreferencesStore,
walletManagersFacade = walletManagersFacade,
userWalletsStore = userWalletsStore,
expressAssetsStore = expressAssetsStore,
walletManagersFacade = walletManagersFacade,
cacheRegistry = cacheRegistry,
appPreferencesStore = appPreferencesStore,
dispatchers = dispatchers,
swapServiceLoader = swapServiceLoader,
)
}
@ -84,15 +81,6 @@ internal object TokensDataModule {
)
}
@Provides
@Singleton
fun provideDefaultMarketCoinsRepository(
expressAssetsStore: ExpressAssetsStore,
coroutineDispatcherProvider: CoroutineDispatcherProvider,
): MarketCryptoCurrencyRepository {
return DefaultMarketCryptoCurrencyRepository(expressAssetsStore, coroutineDispatcherProvider)
}
@Provides
@Singleton
fun provideCurrencyChecksRepository(

View file

@ -12,18 +12,14 @@ import com.tangem.data.tokens.utils.CustomTokensMerger
import com.tangem.data.tokens.utils.UserTokensBackwardCompatibility
import com.tangem.datasource.api.common.response.ApiResponseError
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.express.TangemExpressApi
import com.tangem.datasource.api.express.models.TangemExpressValues.EMPTY_CONTRACT_ADDRESS_VALUE
import com.tangem.datasource.api.express.models.request.AssetsRequestBody
import com.tangem.datasource.api.express.models.request.LeastTokenInfo
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.datasource.exchangeservice.swap.SwapServiceLoader
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.getObject
import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull
import com.tangem.datasource.local.preferences.utils.storeObject
import com.tangem.datasource.local.token.ExpressAssetsStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.core.error.DataError
import com.tangem.domain.demo.DemoConfig
@ -46,12 +42,11 @@ import com.tangem.blockchain.common.FeePaidCurrency as FeePaidSdkCurrency
@Suppress("LargeClass", "LongParameterList", "TooManyFunctions")
internal class DefaultCurrenciesRepository(
private val tangemTechApi: TangemTechApi,
private val tangemExpressApi: TangemExpressApi,
private val userWalletsStore: UserWalletsStore,
private val walletManagersFacade: WalletManagersFacade,
private val expressAssetsStore: ExpressAssetsStore,
private val cacheRegistry: CacheRegistry,
private val appPreferencesStore: AppPreferencesStore,
private val swapServiceLoader: SwapServiceLoader,
private val dispatchers: CoroutineDispatcherProvider,
) : CurrenciesRepository {
@ -298,23 +293,28 @@ internal class DefaultCurrenciesRepository(
userWalletId: UserWalletId,
id: CryptoCurrency.ID,
): CryptoCurrency = withContext(dispatchers.io) {
val userWallet = getUserWallet(userWalletId)
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true)
val response = requireNotNull(
value = getSavedUserTokensResponseSync(key = userWalletId),
lazyMessage = {
"Unable to find tokens response for user wallet with provided ID: $userWalletId"
},
)
responseCurrenciesFactory.createCurrency(
currencyId = id,
response = response,
scanResponse = userWallet.scanResponse,
)
getMultiCurrencyWalletCurrency(userWalletId, id.value)
}
override suspend fun getMultiCurrencyWalletCurrency(userWalletId: UserWalletId, id: String): CryptoCurrency =
withContext(dispatchers.io) {
val userWallet = getUserWallet(userWalletId)
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true)
val response = requireNotNull(
value = getSavedUserTokensResponseSync(key = userWalletId),
lazyMessage = {
"Unable to find tokens response for user wallet with provided ID: $userWalletId"
},
)
responseCurrenciesFactory.createCurrency(
currencyId = id,
response = response,
scanResponse = userWallet.scanResponse,
)
}
override suspend fun getNetworkCoin(
userWalletId: UserWalletId,
networkId: Network.ID,
@ -565,27 +565,7 @@ internal class DefaultCurrenciesRepository(
userWalletId: UserWalletId,
userTokens: UserTokensResponse,
) {
try {
val tokensList = userTokens.tokens
.map {
LeastTokenInfo(
contractAddress = it.contractAddress ?: EMPTY_CONTRACT_ADDRESS_VALUE,
network = it.networkId,
)
}
if (tokensList.isNotEmpty()) {
val response = tangemExpressApi.getAssets(
AssetsRequestBody(
tokensList = tokensList,
),
)
expressAssetsStore.store(userWalletId, response.getOrThrow())
}
} catch (e: Throwable) {
Timber.e(e, "Unable to fetch assets for: ${userWalletId.stringValue}")
}
swapServiceLoader.update(userWalletId, userTokens)
}
private suspend fun handleFetchTokensError(userWallet: UserWallet, e: ApiResponseError): UserTokensResponse {

View file

@ -6,13 +6,17 @@ import com.tangem.blockchain.common.MinimumSendAmountProvider
import com.tangem.blockchain.common.ReserveAmountProvider
import com.tangem.blockchain.common.UtxoAmountLimitProvider
import com.tangem.data.tokens.converters.UtxoConverter
import com.tangem.domain.staking.model.stakekit.YieldBalance
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.CurrencyAmount
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.model.blockchains.UtxoAmountLimit
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
import com.tangem.domain.tokens.repository.CurrencyChecksRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.extensions.isZero
import kotlinx.coroutines.withContext
import java.math.BigDecimal
@ -118,4 +122,23 @@ internal class DefaultCurrencyChecksRepository(
}
return utxoAmount?.let(UtxoConverter()::convert)
}
override suspend fun getRentInfoWarning(
userWalletId: UserWalletId,
currencyStatus: CryptoCurrencyStatus,
balanceAfterTransaction: BigDecimal?,
): CryptoCurrencyWarning.Rent? {
val rentData = walletManagersFacade.getRentInfo(userWalletId, currencyStatus.currency.network) ?: return null
val balanceValue = currencyStatus.value as? CryptoCurrencyStatus.Loaded ?: return null
val stakingTotalBalance =
(balanceValue.yieldBalance as? YieldBalance.Data)?.getTotalStakingBalance() ?: BigDecimal.ZERO
val amount = balanceAfterTransaction ?: balanceValue.amount
return when {
amount.isZero() && stakingTotalBalance.isZero() -> null
amount < rentData.exemptionAmount && stakingTotalBalance.isZero() -> {
CryptoCurrencyWarning.Rent(rentData.rent, rentData.exemptionAmount)
}
else -> null
}
}
}

View file

@ -1,33 +0,0 @@
package com.tangem.data.tokens.repository
import com.tangem.datasource.api.express.models.TangemExpressValues.EMPTY_CONTRACT_ADDRESS_VALUE
import com.tangem.datasource.local.token.ExpressAssetsStore
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.repository.MarketCryptoCurrencyRepository
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
class DefaultMarketCryptoCurrencyRepository(
private val expressAssetsStore: ExpressAssetsStore,
private val dispatchers: CoroutineDispatcherProvider,
) : MarketCryptoCurrencyRepository {
override suspend fun isExchangeable(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean {
return getExchangeableFlag(userWalletId, cryptoCurrency) && !cryptoCurrency.isCustom
}
private suspend fun getExchangeableFlag(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean {
return withContext(dispatchers.io) {
val contractAddress =
(cryptoCurrency as? CryptoCurrency.Token)?.contractAddress ?: EMPTY_CONTRACT_ADDRESS_VALUE
val asset = expressAssetsStore.getSyncOrNull(userWalletId)?.find {
it.network == cryptoCurrency.network.backendId &&
it.contractAddress.equals(contractAddress, ignoreCase = true)
}
asset?.exchangeAvailable ?: false
}
}
}