Updated on 2026-08-14

This commit is contained in:
Tangem 2024-07-02 21:20:02 +08:00
parent 5f42e80618
commit efc8c003bd
5 changed files with 111 additions and 82 deletions

View file

@ -87,8 +87,11 @@ internal object TokensDataModule {
@Provides
@Singleton
fun provideDefaultMarketCoinsRepository(assetsStore: AssetsStore): MarketCryptoCurrencyRepository {
return DefaultMarketCryptoCurrencyRepository(assetsStore)
fun provideDefaultMarketCoinsRepository(
assetsStore: AssetsStore,
coroutineDispatcherProvider: CoroutineDispatcherProvider,
): MarketCryptoCurrencyRepository {
return DefaultMarketCryptoCurrencyRepository(assetsStore, coroutineDispatcherProvider)
}
@Provides

View file

@ -302,26 +302,28 @@ internal class DefaultCurrenciesRepository(
networkId: Network.ID,
derivationPath: Network.DerivationPath,
): CryptoCurrency.Coin {
val userWallet = getUserWallet(userWalletId)
ensureIsCorrectUserWallet(userWallet = userWallet, isMultiCurrencyWalletExpected = true)
return withContext(dispatchers.io) {
val userWallet = getUserWallet(userWalletId)
ensureIsCorrectUserWallet(userWallet = userWallet, isMultiCurrencyWalletExpected = true)
fetchTokensIfCacheExpired(userWallet = userWallet, refresh = false)
fetchTokensIfCacheExpired(userWallet = userWallet, refresh = false)
val storedTokens = requireNotNull(userTokensStore.getSyncOrNull(userWallet.walletId)) {
"Unable to find tokens response for user wallet with provided ID: $userWalletId"
val storedTokens = requireNotNull(userTokensStore.getSyncOrNull(userWallet.walletId)) {
"Unable to find tokens response for user wallet with provided ID: $userWalletId"
}
val blockchain = Blockchain.fromId(networkId.value)
val blockchainNetworkId = blockchain.toNetworkId()
val coinId = blockchain.toCoinId()
val storedCoin = storedTokens.tokens
.find {
it.networkId == blockchainNetworkId && it.id == coinId && it.derivationPath == derivationPath.value
} ?: error("Coin in this network $networkId not found")
val coin = responseCurrenciesFactory.createCurrency(storedCoin, userWallet.scanResponse)
coin as? CryptoCurrency.Coin ?: error("Unable to create currency")
}
val blockchain = Blockchain.fromId(networkId.value)
val blockchainNetworkId = blockchain.toNetworkId()
val coinId = blockchain.toCoinId()
val storedCoin = storedTokens.tokens
.find {
it.networkId == blockchainNetworkId && it.id == coinId && it.derivationPath == derivationPath.value
} ?: error("Coin in this network $networkId not found")
val coin = responseCurrenciesFactory.createCurrency(storedCoin, userWallet.scanResponse)
return coin as? CryptoCurrency.Coin ?: error("Unable to create currency")
}
override fun isTokensGrouped(userWalletId: UserWalletId): Flow<Boolean> {
@ -382,29 +384,31 @@ internal class DefaultCurrenciesRepository(
}
override suspend fun getFeePaidCurrency(userWalletId: UserWalletId, currency: CryptoCurrency): FeePaidCurrency {
val blockchain = Blockchain.fromId(currency.network.id.value)
return when (val feePaidCurrency = blockchain.feePaidCurrency()) {
FeePaidSdkCurrency.Coin -> FeePaidCurrency.Coin
FeePaidSdkCurrency.SameCurrency -> FeePaidCurrency.SameCurrency
is FeePaidSdkCurrency.Token -> {
val balance = walletManagersFacade.tokenBalance(
userWalletId = userWalletId,
network = currency.network,
name = feePaidCurrency.token.name,
symbol = feePaidCurrency.token.symbol,
contractAddress = feePaidCurrency.token.contractAddress,
decimals = feePaidCurrency.token.decimals,
id = feePaidCurrency.token.id,
)
FeePaidCurrency.Token(
tokenId = getTokenId(network = currency.network, sdkToken = feePaidCurrency.token),
name = feePaidCurrency.token.name,
symbol = feePaidCurrency.token.symbol,
contractAddress = feePaidCurrency.token.contractAddress,
balance = balance,
)
return withContext(dispatchers.io) {
val blockchain = Blockchain.fromId(currency.network.id.value)
when (val feePaidCurrency = blockchain.feePaidCurrency()) {
FeePaidSdkCurrency.Coin -> FeePaidCurrency.Coin
FeePaidSdkCurrency.SameCurrency -> FeePaidCurrency.SameCurrency
is FeePaidSdkCurrency.Token -> {
val balance = walletManagersFacade.tokenBalance(
userWalletId = userWalletId,
network = currency.network,
name = feePaidCurrency.token.name,
symbol = feePaidCurrency.token.symbol,
contractAddress = feePaidCurrency.token.contractAddress,
decimals = feePaidCurrency.token.decimals,
id = feePaidCurrency.token.id,
)
FeePaidCurrency.Token(
tokenId = getTokenId(network = currency.network, sdkToken = feePaidCurrency.token),
name = feePaidCurrency.token.name,
symbol = feePaidCurrency.token.symbol,
contractAddress = feePaidCurrency.token.contractAddress,
balance = balance,
)
}
is FeePaidSdkCurrency.FeeResource -> FeePaidCurrency.FeeResource(currency = feePaidCurrency.currency)
}
is FeePaidSdkCurrency.FeeResource -> FeePaidCurrency.FeeResource(currency = feePaidCurrency.currency)
}
}

View file

@ -5,9 +5,12 @@ import com.tangem.datasource.local.token.AssetsStore
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 assetsStore: AssetsStore,
private val dispatchers: CoroutineDispatcherProvider,
) : MarketCryptoCurrencyRepository {
override suspend fun isExchangeable(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean {
@ -15,11 +18,16 @@ class DefaultMarketCryptoCurrencyRepository(
}
private suspend fun getExchangeableFlag(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean {
val contractAddress = (cryptoCurrency as? CryptoCurrency.Token)?.contractAddress ?: EMPTY_CONTRACT_ADDRESS_VALUE
return withContext(dispatchers.io) {
val contractAddress =
(cryptoCurrency as? CryptoCurrency.Token)?.contractAddress ?: EMPTY_CONTRACT_ADDRESS_VALUE
return assetsStore.getSyncOrNull(userWalletId)?.find {
it.network == cryptoCurrency.network.backendId &&
it.contractAddress.equals(contractAddress, ignoreCase = true)
}?.exchangeAvailable ?: false
val asset = assetsStore.getSyncOrNull(userWalletId)?.find {
it.network == cryptoCurrency.network.backendId &&
it.contractAddress.equals(contractAddress, ignoreCase = true)
}
asset?.exchangeAvailable ?: false
}
}
}

View file

@ -35,16 +35,19 @@ class DefaultTxHistoryRepository(
private val sdkPageConverter by lazy { SdkPageConverter() }
override suspend fun getTxHistoryItemsCount(userWalletId: UserWalletId, currency: CryptoCurrency): Int {
val userWallet = getUserWallet(userWalletId)
val state = walletManagersFacade.getTxHistoryState(
userWalletId = userWallet.walletId,
currency = currency,
)
return when (state) {
is TxHistoryState.Failed.FetchError -> throw TxHistoryStateError.DataError(state.exception)
is TxHistoryState.NotImplemented -> throw TxHistoryStateError.TxHistoryNotImplemented
is TxHistoryState.Success.Empty -> throw TxHistoryStateError.EmptyTxHistories
is TxHistoryState.Success.HasTransactions -> state.txCount
return withContext(dispatchers.io) {
val userWallet = getUserWallet(userWalletId)
val state = walletManagersFacade.getTxHistoryState(
userWalletId = userWallet.walletId,
currency = currency,
)
when (state) {
is TxHistoryState.Failed.FetchError -> throw TxHistoryStateError.DataError(state.exception)
is TxHistoryState.NotImplemented -> throw TxHistoryStateError.TxHistoryNotImplemented
is TxHistoryState.Success.Empty -> throw TxHistoryStateError.EmptyTxHistories
is TxHistoryState.Success.HasTransactions -> state.txCount
}
}
}

View file

@ -87,11 +87,13 @@ class DefaultWalletManagersFacade(
Blockchain.fromId(it.id.value) to it.derivationPath.value
}
walletManagersStore.remove(userWalletId) { walletManager ->
val wallet = walletManager.wallet
val blockchainToDerivationPath = wallet.blockchain to wallet.publicKey.derivationPath?.rawPath
withContext(dispatchers.io) {
walletManagersStore.remove(userWalletId) { walletManager ->
val wallet = walletManager.wallet
val blockchainToDerivationPath = wallet.blockchain to wallet.publicKey.derivationPath?.rawPath
blockchainToDerivationPath in blockchainsToDerivationPaths
blockchainToDerivationPath in blockchainsToDerivationPaths
}
}
}
@ -110,18 +112,20 @@ class DefaultWalletManagersFacade(
network: Network,
networkTokens: List<CryptoCurrency.Token>,
) {
val walletManager = walletManagersStore.getSyncOrNull(
userWalletId = userWalletId,
blockchain = Blockchain.fromId(network.id.value),
derivationPath = network.derivationPath.value,
) ?: return
val tokensToRemove = sdkTokenConverter.convertList(networkTokens)
withContext(dispatchers.io) {
val walletManager = walletManagersStore.getSyncOrNull(
userWalletId = userWalletId,
blockchain = Blockchain.fromId(network.id.value),
derivationPath = network.derivationPath.value,
) ?: return@withContext
val tokensToRemove = sdkTokenConverter.convertList(networkTokens)
tokensToRemove.forEach { token ->
walletManager.removeToken(token)
tokensToRemove.forEach { token ->
walletManager.removeToken(token)
}
walletManagersStore.store(userWalletId, walletManager)
}
walletManagersStore.store(userWalletId, walletManager)
}
override suspend fun updatePendingTransactions(
@ -576,12 +580,16 @@ class DefaultWalletManagersFacade(
userWalletId: UserWalletId,
currency: CryptoCurrency,
): AssetRequirementsCondition? {
val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = currency.network)
val currencyType = cryptoCurrencyTypeConverter.convert(currency)
if (walletManager !is AssetRequirementsManager || !walletManager.hasRequirements(currencyType)) return null
return withContext(dispatchers.io) {
val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = currency.network)
val currencyType = cryptoCurrencyTypeConverter.convert(currency)
if (walletManager !is AssetRequirementsManager || !walletManager.hasRequirements(currencyType)) {
return@withContext null
}
val condition = walletManager.requirementsCondition(currencyType) ?: return null
return requirementsConditionConverter.convert(condition)
val condition = walletManager.requirementsCondition(currencyType) ?: return@withContext null
requirementsConditionConverter.convert(condition)
}
}
override suspend fun associateAsset(
@ -589,15 +597,18 @@ class DefaultWalletManagersFacade(
currency: CryptoCurrency,
signer: CommonSigner,
): SimpleResult {
val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = currency.network)
val currencyType = cryptoCurrencyTypeConverter.convert(currency)
return withContext(dispatchers.io) {
val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = currency.network)
val currencyType = cryptoCurrencyTypeConverter.convert(currency)
if (walletManager !is AssetRequirementsManager) {
return SimpleResult.Failure(
BlockchainSdkError.CustomError("WalletManager is not implemented AssetRequirementsManager"),
)
if (walletManager !is AssetRequirementsManager) {
return@withContext SimpleResult.Failure(
BlockchainSdkError.CustomError("WalletManager is not implemented AssetRequirementsManager"),
)
}
walletManager.fulfillRequirements(currencyType, signer)
}
return walletManager.fulfillRequirements(currencyType, signer)
}
override suspend fun checkUtxoConsolidationAvailability(userWalletId: UserWalletId, network: Network): Boolean {