Updated on 2026-08-14
This commit is contained in:
commit
f0d03e3648
286 changed files with 6353 additions and 5898 deletions
|
|
@ -12,13 +12,11 @@ android {
|
|||
dependencies {
|
||||
|
||||
/** Project - Domain */
|
||||
implementation(projects.domain.core)
|
||||
implementation(projects.domain.appTheme)
|
||||
implementation(projects.domain.appTheme.models)
|
||||
|
||||
/** Project - Data */
|
||||
implementation(projects.core.datasource)
|
||||
implementation(projects.data.common)
|
||||
|
||||
/** Project - Utils */
|
||||
implementation(projects.core.utils)
|
||||
|
|
@ -29,6 +27,4 @@ dependencies {
|
|||
|
||||
/** Other */
|
||||
implementation(deps.kotlin.coroutines)
|
||||
implementation(deps.timber)
|
||||
implementation(deps.jodatime)
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.data.apptheme
|
||||
|
||||
import com.tangem.datasource.local.apptheme.AppThemeModeStore
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
internal class DefaultAppThemeModeRepository(
|
||||
private val appThemeModeStore: AppThemeModeStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : AppThemeModeRepository {
|
||||
|
||||
override fun getAppThemeMode(): Flow<AppThemeMode> {
|
||||
return channelFlow {
|
||||
launch(dispatchers.io) {
|
||||
if (appThemeModeStore.isEmpty()) {
|
||||
appThemeModeStore.store(AppThemeMode.DEFAULT)
|
||||
}
|
||||
}
|
||||
|
||||
launch(dispatchers.io) {
|
||||
appThemeModeStore.get().collect(::send)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun changeAppThemeMode(mode: AppThemeMode) {
|
||||
withContext(dispatchers.io) {
|
||||
appThemeModeStore.store(mode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
package com.tangem.data.apptheme
|
||||
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
internal class MockAppThemeModeRepository : AppThemeModeRepository {
|
||||
|
||||
private val appThemeModeFlow = MutableStateFlow(AppThemeMode.DEFAULT)
|
||||
|
||||
override fun getAppThemeMode(): Flow<AppThemeMode> {
|
||||
return appThemeModeFlow
|
||||
}
|
||||
|
||||
override suspend fun changeAppThemeMode(mode: AppThemeMode) {
|
||||
appThemeModeFlow.value = mode
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.data.apptheme.di
|
||||
|
||||
import com.tangem.data.apptheme.MockAppThemeModeRepository
|
||||
import com.tangem.data.apptheme.DefaultAppThemeModeRepository
|
||||
import com.tangem.datasource.local.apptheme.AppThemeModeStore
|
||||
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -14,7 +16,10 @@ internal object AppThemeModeDataModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAppThemeModeRepository(): AppThemeModeRepository {
|
||||
return MockAppThemeModeRepository()
|
||||
fun provideAppThemeModeRepository(
|
||||
appThemeModeStore: AppThemeModeStore,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): AppThemeModeRepository {
|
||||
return DefaultAppThemeModeRepository(appThemeModeStore, dispatchers)
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ dependencies {
|
|||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.txhistory.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
|
||||
/** Project - Data */
|
||||
|
|
|
|||
|
|
@ -2,14 +2,17 @@ package com.tangem.data.tokens.di
|
|||
|
||||
import com.tangem.data.common.cache.CacheRegistry
|
||||
import com.tangem.data.tokens.repository.DefaultCurrenciesRepository
|
||||
import com.tangem.data.tokens.repository.DefaultMarketCryptoCurrencyRepository
|
||||
import com.tangem.data.tokens.repository.DefaultNetworksRepository
|
||||
import com.tangem.data.tokens.repository.DefaultQuotesRepository
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.appcurrency.SelectedAppCurrencyStore
|
||||
import com.tangem.datasource.local.quote.QuotesStore
|
||||
import com.tangem.datasource.local.token.UserMarketCoinsStore
|
||||
import com.tangem.datasource.local.token.UserTokensStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.MarketCryptoCurrencyRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
|
|
@ -30,10 +33,18 @@ internal object TokensDataModule {
|
|||
tangemTechApi: TangemTechApi,
|
||||
userTokensStore: UserTokensStore,
|
||||
userWalletsStore: UserWalletsStore,
|
||||
userMarketCoinsStore: UserMarketCoinsStore,
|
||||
cacheRegistry: CacheRegistry,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): CurrenciesRepository {
|
||||
return DefaultCurrenciesRepository(tangemTechApi, userTokensStore, userWalletsStore, cacheRegistry, dispatchers)
|
||||
return DefaultCurrenciesRepository(
|
||||
tangemTechApi = tangemTechApi,
|
||||
userTokensStore = userTokensStore,
|
||||
userWalletsStore = userWalletsStore,
|
||||
userMarketCoinsStore = userMarketCoinsStore,
|
||||
cacheRegistry = cacheRegistry,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
@ -46,11 +57,11 @@ internal object TokensDataModule {
|
|||
dispatchers: CoroutineDispatcherProvider,
|
||||
): QuotesRepository {
|
||||
return DefaultQuotesRepository(
|
||||
tangemTechApi,
|
||||
quotesStore,
|
||||
selectedAppCurrencyStore,
|
||||
cacheRegistry,
|
||||
dispatchers,
|
||||
tangemTechApi = tangemTechApi,
|
||||
quotesStore = quotesStore,
|
||||
selectedAppCurrencyStore = selectedAppCurrencyStore,
|
||||
cacheRegistry = cacheRegistry,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -64,11 +75,19 @@ internal object TokensDataModule {
|
|||
dispatchers: CoroutineDispatcherProvider,
|
||||
): NetworksRepository {
|
||||
return DefaultNetworksRepository(
|
||||
walletManagersFacade,
|
||||
userWalletsStore,
|
||||
userTokensStore,
|
||||
cacheRegistry,
|
||||
dispatchers,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
userWalletsStore = userWalletsStore,
|
||||
userTokensStore = userTokensStore,
|
||||
cacheRegistry = cacheRegistry,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideDefaultMarketCoinsRepository(
|
||||
userMarketCoinsStore: UserMarketCoinsStore,
|
||||
): MarketCryptoCurrencyRepository {
|
||||
return DefaultMarketCryptoCurrencyRepository(userMarketCoinsStore)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,19 @@
|
|||
package com.tangem.data.tokens.repository
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.data.common.cache.CacheRegistry
|
||||
import com.tangem.data.tokens.utils.CardCurrenciesFactory
|
||||
import com.tangem.data.tokens.utils.ResponseCurrenciesFactory
|
||||
import com.tangem.data.tokens.utils.UserTokensResponseFactory
|
||||
import com.tangem.data.tokens.utils.*
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.local.token.UserMarketCoinsStore
|
||||
import com.tangem.datasource.local.token.UserTokensStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.core.error.DataError
|
||||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
|
@ -27,6 +29,7 @@ internal class DefaultCurrenciesRepository(
|
|||
private val tangemTechApi: TangemTechApi,
|
||||
private val userTokensStore: UserTokensStore,
|
||||
private val userWalletsStore: UserWalletsStore,
|
||||
private val userMarketCoinsStore: UserMarketCoinsStore,
|
||||
private val cacheRegistry: CacheRegistry,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : CurrenciesRepository {
|
||||
|
|
@ -53,6 +56,53 @@ internal class DefaultCurrenciesRepository(
|
|||
storeAndPushTokens(userWalletId, response)
|
||||
}
|
||||
|
||||
override suspend fun addCurrencies(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
||||
return withContext(dispatchers.io) {
|
||||
val savedCurrencies = requireNotNull(
|
||||
value = userTokensStore.getSyncOrNull(userWalletId),
|
||||
lazyMessage = { "Saved tokens empty. Can not perform add currencies action" },
|
||||
)
|
||||
|
||||
val newCoins = createCoinsForNewTokens(
|
||||
userWalletId = userWalletId,
|
||||
newTokens = currencies.filterIsInstance<CryptoCurrency.Token>(),
|
||||
savedCurrencies = savedCurrencies.tokens,
|
||||
)
|
||||
|
||||
val newCurrencies = newCoins + currencies
|
||||
|
||||
storeAndPushTokens(
|
||||
userWalletId = userWalletId,
|
||||
response = savedCurrencies.copy(
|
||||
tokens = savedCurrencies.tokens + newCurrencies.map(userTokensResponseFactory::createResponseToken),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun createCoinsForNewTokens(
|
||||
userWalletId: UserWalletId,
|
||||
newTokens: List<CryptoCurrency.Token>,
|
||||
savedCurrencies: List<UserTokensResponse.Token>,
|
||||
): List<CryptoCurrency.Coin> {
|
||||
return newTokens
|
||||
.filterNot { savedCurrencies.hasCoinForToken(it) } // tokens without coins
|
||||
.mapNotNull {
|
||||
CryptoCurrencyFactory().createCoin(
|
||||
blockchain = getBlockchain(networkId = it.network.id),
|
||||
derivationStyleProvider = getUserWallet(userWalletId).scanResponse.derivationStyleProvider,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<UserTokensResponse.Token>.hasCoinForToken(token: CryptoCurrency.Token): Boolean {
|
||||
return any {
|
||||
val blockchain = getBlockchain(networkId = token.network.id)
|
||||
|
||||
it.id == getCoinId(blockchain).rawCurrencyId
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun removeCurrency(userWalletId: UserWalletId, currency: CryptoCurrency) =
|
||||
withContext(dispatchers.io) {
|
||||
val savedCurrencies = requireNotNull(
|
||||
|
|
@ -69,6 +119,23 @@ internal class DefaultCurrenciesRepository(
|
|||
)
|
||||
}
|
||||
|
||||
override suspend fun removeCurrencies(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
||||
return withContext(dispatchers.io) {
|
||||
val savedCurrencies = requireNotNull(
|
||||
value = userTokensStore.getSyncOrNull(userWalletId),
|
||||
lazyMessage = { "Saved tokens empty. Can not perform remove currencies action" },
|
||||
)
|
||||
|
||||
val tokens = currencies.map(userTokensResponseFactory::createResponseToken)
|
||||
storeAndPushTokens(
|
||||
userWalletId = userWalletId,
|
||||
response = savedCurrencies.copy(
|
||||
tokens = savedCurrencies.tokens.filterNot(tokens::contains),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getSingleCurrencyWalletPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency {
|
||||
return withContext(dispatchers.io) {
|
||||
val userWallet = getUserWallet(userWalletId)
|
||||
|
|
@ -126,6 +193,27 @@ internal class DefaultCurrenciesRepository(
|
|||
responseCurrenciesFactory.createCurrency(id, response, userWallet.scanResponse.card)
|
||||
}
|
||||
|
||||
override suspend fun getNetworkCoin(userWalletId: UserWalletId, networkId: Network.ID): CryptoCurrency.Coin {
|
||||
val userWallet = getUserWallet(userWalletId)
|
||||
ensureIsCorrectUserWallet(userWallet = userWallet, isMultiCurrencyWalletExpected = true)
|
||||
|
||||
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 storedCoin = storedTokens.tokens.find { it.networkId == Blockchain.fromId(networkId.value).toNetworkId() }
|
||||
?: error("Coin in this network $networkId not found")
|
||||
|
||||
val coin = responseCurrenciesFactory.createCurrency(
|
||||
responseToken = storedCoin,
|
||||
card = userWallet.scanResponse.card,
|
||||
)
|
||||
|
||||
return coin as? CryptoCurrency.Coin ?: error("Unable to create currency")
|
||||
}
|
||||
|
||||
override fun isTokensGrouped(userWalletId: UserWalletId): Flow<Boolean> {
|
||||
return channelFlow {
|
||||
ensureIsCorrectUserWallet(userWalletId, isMultiCurrencyWalletExpected = true)
|
||||
|
|
@ -172,6 +260,7 @@ internal class DefaultCurrenciesRepository(
|
|||
val response = tangemTechApi.getUserTokens(userWallet.walletId.stringValue)
|
||||
|
||||
userTokensStore.store(userWallet.walletId, response)
|
||||
fetchUserMarketCoinsByIds(userWallet.walletId, response)
|
||||
} catch (e: Throwable) {
|
||||
handleFetchTokensErrorOrThrow(userWallet, e)
|
||||
}
|
||||
|
|
@ -182,6 +271,17 @@ internal class DefaultCurrenciesRepository(
|
|||
tangemTechApi.saveUserTokens(userWalletId.stringValue, response)
|
||||
}
|
||||
|
||||
private suspend fun fetchUserMarketCoinsByIds(userWalletId: UserWalletId, userTokens: UserTokensResponse) {
|
||||
try {
|
||||
val response = tangemTechApi.getCoins(
|
||||
networkIds = userTokens.tokens.joinToString(separator = ",") { it.networkId },
|
||||
)
|
||||
userMarketCoinsStore.store(userWalletId, response)
|
||||
} catch (e: Throwable) {
|
||||
Timber.e("Unable to fetch user market coins for: ${userWalletId.stringValue} ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleFetchTokensErrorOrThrow(userWallet: UserWallet, error: Throwable) {
|
||||
val errorMessage = error.message ?: throw error
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.data.tokens.repository
|
||||
|
||||
import com.tangem.datasource.local.token.UserMarketCoinsStore
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.repository.MarketCryptoCurrencyRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
class DefaultMarketCryptoCurrencyRepository(
|
||||
private val userMarketCoinsStore: UserMarketCoinsStore,
|
||||
) : MarketCryptoCurrencyRepository {
|
||||
|
||||
override suspend fun isExchangeable(userWalletId: UserWalletId, cryptoCurrencyId: CryptoCurrency.ID): Boolean {
|
||||
return userMarketCoinsStore.getSyncOrNull(userWalletId)?.coins
|
||||
?.firstOrNull { it.id == cryptoCurrencyId.rawCurrencyId }
|
||||
?.networks
|
||||
?.firstOrNull { it.networkId == cryptoCurrencyId.rawNetworkId }?.exchangeable ?: false
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ import com.tangem.domain.tokens.models.CryptoCurrency
|
|||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.walletmanager.model.UpdateWalletManagerResult
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.addOrReplace
|
||||
|
|
@ -68,25 +69,29 @@ internal class DefaultNetworksRepository(
|
|||
networks: Set<Network.ID>,
|
||||
refresh: Boolean,
|
||||
) {
|
||||
cacheRegistry.invokeOnExpire(
|
||||
key = getNetworksStatusesCacheKey(userWalletId),
|
||||
skipCache = refresh,
|
||||
block = { fetchNetworksStatuses(userWalletId, networks) },
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun fetchNetworksStatuses(userWalletId: UserWalletId, networks: Set<Network.ID>) {
|
||||
coroutineScope {
|
||||
networks
|
||||
.map { networkId ->
|
||||
async {
|
||||
fetchNetworkStatus(userWalletId, networkId)
|
||||
fetchNetworkStatusIfCacheExpired(userWalletId, networkId, refresh)
|
||||
}
|
||||
}
|
||||
.awaitAll()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchNetworkStatusIfCacheExpired(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
refresh: Boolean,
|
||||
) {
|
||||
cacheRegistry.invokeOnExpire(
|
||||
key = getNetworksStatusesCacheKey(userWalletId, networkId),
|
||||
skipCache = refresh,
|
||||
block = { fetchNetworkStatus(userWalletId, networkId) },
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun fetchNetworkStatus(userWalletId: UserWalletId, networkId: Network.ID) {
|
||||
val currencies = getCurrencies(userWalletId)
|
||||
.asSequence()
|
||||
|
|
@ -97,6 +102,17 @@ internal class DefaultNetworksRepository(
|
|||
networkId = networkId,
|
||||
extraTokens = currencies.filterIsInstance<CryptoCurrency.Token>().toSet(),
|
||||
)
|
||||
|
||||
// Invalidate cache key if wallet manager update failed
|
||||
when (result) {
|
||||
is UpdateWalletManagerResult.Verified,
|
||||
is UpdateWalletManagerResult.NoAccount,
|
||||
-> Unit
|
||||
is UpdateWalletManagerResult.Unreachable,
|
||||
is UpdateWalletManagerResult.MissedDerivation,
|
||||
-> cacheRegistry.invalidate(getNetworksStatusesCacheKey(userWalletId, networkId))
|
||||
}
|
||||
|
||||
val networkStatus = networkStatusFactory.createNetworkStatus(
|
||||
networkId = networkId,
|
||||
result = result,
|
||||
|
|
@ -126,5 +142,7 @@ internal class DefaultNetworksRepository(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getNetworksStatusesCacheKey(userWalletId: UserWalletId): String = "network_status_$userWalletId"
|
||||
private fun getNetworksStatusesCacheKey(userWalletId: UserWalletId, nerworkId: Network.ID): String {
|
||||
return "network_status_${userWalletId}_${nerworkId.value}"
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,9 @@ package com.tangem.data.tokens.utils
|
|||
|
||||
import com.tangem.domain.tokens.model.NetworkAddress
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.tokens.model.PendingTransaction
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.domain.walletmanager.model.CryptoCurrencyAmount
|
||||
import com.tangem.domain.walletmanager.model.CryptoCurrencyTransaction
|
||||
import com.tangem.domain.walletmanager.model.UpdateWalletManagerResult
|
||||
|
|
@ -31,7 +31,6 @@ internal class NetworkStatusFactory {
|
|||
address = getNetworkAddress(result.defaultAddress, result.addresses),
|
||||
amounts = formatAmounts(result.currenciesAmounts, currencies),
|
||||
pendingTransactions = formatTransactions(
|
||||
networksAddresses = result.addresses,
|
||||
transactions = result.currentTransactions,
|
||||
currencies = currencies,
|
||||
),
|
||||
|
|
@ -67,10 +66,9 @@ internal class NetworkStatusFactory {
|
|||
}
|
||||
|
||||
private fun formatTransactions(
|
||||
networksAddresses: Set<String>,
|
||||
transactions: Set<CryptoCurrencyTransaction>,
|
||||
currencies: Set<CryptoCurrency>,
|
||||
): Map<CryptoCurrency.ID, Set<PendingTransaction>> {
|
||||
): Map<CryptoCurrency.ID, Set<TxHistoryItem>> {
|
||||
if (transactions.isEmpty()) return emptyMap()
|
||||
|
||||
return currencies
|
||||
|
|
@ -87,48 +85,13 @@ internal class NetworkStatusFactory {
|
|||
}
|
||||
}
|
||||
|
||||
currency.id to createCurrentTransactions(networksAddresses, currencyTransactions)
|
||||
currency.id to createCurrentTransactions(currencyTransactions)
|
||||
}
|
||||
.toMap()
|
||||
}
|
||||
|
||||
private fun createCurrentTransactions(
|
||||
networksAddresses: Set<String>,
|
||||
transactions: Set<CryptoCurrencyTransaction>,
|
||||
): Set<PendingTransaction> {
|
||||
return transactions.mapNotNullTo(hashSetOf()) { createCurrentTransaction(networksAddresses, it) }
|
||||
}
|
||||
|
||||
private fun createCurrentTransaction(
|
||||
networksAddresses: Set<String>,
|
||||
transaction: CryptoCurrencyTransaction,
|
||||
): PendingTransaction? {
|
||||
val direction = when {
|
||||
transaction.toAddress in networksAddresses -> PendingTransaction.Direction.Incoming(
|
||||
fromAddress = transaction.fromAddress,
|
||||
)
|
||||
transaction.fromAddress in networksAddresses -> PendingTransaction.Direction.Outgoing(
|
||||
toAddress = transaction.toAddress,
|
||||
)
|
||||
else -> {
|
||||
Timber.e(
|
||||
"""
|
||||
Unable to find transaction direction
|
||||
|- To address: ${transaction.toAddress}
|
||||
|- From address: ${transaction.fromAddress}
|
||||
|- Network addresses: $networksAddresses
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return PendingTransaction(
|
||||
amount = transaction.amount,
|
||||
direction = direction,
|
||||
sentAt = transaction.sentAt,
|
||||
)
|
||||
private fun createCurrentTransactions(transactions: Set<CryptoCurrencyTransaction>): Set<TxHistoryItem> {
|
||||
return transactions.mapTo(hashSetOf()) { it.txHistoryItem }
|
||||
}
|
||||
|
||||
private fun getNetworkAddress(defaultAddress: String, availableAddresses: Set<String>): NetworkAddress {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ internal class ResponseCurrenciesFactory(private val demoConfig: DemoConfig) {
|
|||
return response.tokens.mapNotNull { createCurrency(it, card) }
|
||||
}
|
||||
|
||||
private fun createCurrency(responseToken: UserTokensResponse.Token, card: CardDTO): CryptoCurrency? {
|
||||
fun createCurrency(responseToken: UserTokensResponse.Token, card: CardDTO): CryptoCurrency? {
|
||||
var blockchain = Blockchain.fromNetworkId(responseToken.networkId)
|
||||
if (blockchain == null || blockchain == Blockchain.Unknown) {
|
||||
Timber.e("Unable to find a blockchain with the network ID: ${responseToken.networkId}")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue