Updated on 2026-08-14
This commit is contained in:
parent
0bf2decb83
commit
36e7f2d07f
23 changed files with 212 additions and 70 deletions
|
|
@ -30,6 +30,7 @@ dependencies {
|
||||||
|
|
||||||
/** Project - Domain */
|
/** Project - Domain */
|
||||||
implementation(projects.domain.appCurrency.models)
|
implementation(projects.domain.appCurrency.models)
|
||||||
|
implementation(projects.domain.models)
|
||||||
implementation(projects.domain.legacy)
|
implementation(projects.domain.legacy)
|
||||||
implementation(projects.domain.staking.models)
|
implementation(projects.domain.staking.models)
|
||||||
implementation(projects.domain.tokens.models)
|
implementation(projects.domain.tokens.models)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.tangem.datasource.local.datastore.RuntimeDataStore
|
||||||
import com.tangem.datasource.local.network.converter.NetworkStatusConverter
|
import com.tangem.datasource.local.network.converter.NetworkStatusConverter
|
||||||
import com.tangem.datasource.local.network.converter.NetworkStatusDataModelConverter
|
import com.tangem.datasource.local.network.converter.NetworkStatusDataModelConverter
|
||||||
import com.tangem.datasource.local.network.entity.NetworkStatusDM
|
import com.tangem.datasource.local.network.entity.NetworkStatusDM
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.tokens.model.Network
|
import com.tangem.domain.tokens.model.Network
|
||||||
import com.tangem.domain.tokens.model.NetworkStatus
|
import com.tangem.domain.tokens.model.NetworkStatus
|
||||||
import com.tangem.domain.wallets.models.UserWalletId
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
|
|
@ -98,21 +99,42 @@ internal class DefaultNetworksStatusesStore(
|
||||||
cachedStatuses: Set<NetworkStatus>,
|
cachedStatuses: Set<NetworkStatus>,
|
||||||
runtimeStatuses: Set<NetworkStatus>,
|
runtimeStatuses: Set<NetworkStatus>,
|
||||||
): Set<NetworkStatus> {
|
): Set<NetworkStatus> {
|
||||||
val runtimeMap = runtimeStatuses.associateBy { it.network }
|
return runtimeStatuses
|
||||||
val mergedCached = cachedStatuses.filter { it.network !in runtimeMap.keys }
|
.map { runtime ->
|
||||||
|
runtime.takeIf { it.value !is NetworkStatus.Unreachable }
|
||||||
|
?: getCachedStatusIfPossible(cachedStatuses = cachedStatuses, runtime = runtime)
|
||||||
|
}
|
||||||
|
.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
return mergedCached.toSet() + runtimeStatuses
|
private fun getCachedStatusIfPossible(cachedStatuses: Set<NetworkStatus>, runtime: NetworkStatus): NetworkStatus {
|
||||||
|
val cached = cachedStatuses.firstOrNull { it.network == runtime.network } ?: return runtime
|
||||||
|
|
||||||
|
val updatedCachedStatus = when (val status = cached.value) {
|
||||||
|
is NetworkStatus.NoAccount -> status.copy(source = StatusSource.ONLY_CACHE)
|
||||||
|
is NetworkStatus.Verified -> status.copy(source = StatusSource.ONLY_CACHE)
|
||||||
|
is NetworkStatus.Refreshing,
|
||||||
|
is NetworkStatus.Unreachable,
|
||||||
|
is NetworkStatus.MissedDerivation,
|
||||||
|
-> null
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (updatedCachedStatus != null) {
|
||||||
|
cached.copy(value = updatedCachedStatus)
|
||||||
|
} else {
|
||||||
|
runtime
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun storeNetworkStatusInPersistence(userWalletId: UserWalletId, networkStatus: NetworkStatus) {
|
private suspend fun storeNetworkStatusInPersistence(userWalletId: UserWalletId, networkStatus: NetworkStatus) {
|
||||||
val network = networkStatus.network
|
val network = networkStatus.network
|
||||||
|
|
||||||
|
// Converter will return null if the network status is not supported
|
||||||
|
val newStatus = NetworkStatusDataModelConverter.convert(value = networkStatus) ?: return
|
||||||
|
|
||||||
persistenceDataStore.updateData { storedStatuses ->
|
persistenceDataStore.updateData { storedStatuses ->
|
||||||
val userWalletStatuses = storedStatuses[userWalletId.stringValue] ?: emptySet()
|
val userWalletStatuses = storedStatuses[userWalletId.stringValue].orEmpty()
|
||||||
val updatedStatuses = userWalletStatuses.addOrReplace(
|
val updatedStatuses = userWalletStatuses.addOrReplace(item = newStatus) { it.networkId == network.id }
|
||||||
item = NetworkStatusDataModelConverter.convert(value = networkStatus),
|
|
||||||
predicate = { it.networkId == network.id },
|
|
||||||
)
|
|
||||||
|
|
||||||
storedStatuses.toMutableMap().apply {
|
storedStatuses.toMutableMap().apply {
|
||||||
this[userWalletId.stringValue] = updatedStatuses
|
this[userWalletId.stringValue] = updatedStatuses
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.datasource.local.network.converter
|
package com.tangem.datasource.local.network.converter
|
||||||
|
|
||||||
import com.tangem.datasource.local.network.entity.NetworkStatusDM
|
import com.tangem.datasource.local.network.entity.NetworkStatusDM
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.tokens.model.Network
|
import com.tangem.domain.tokens.model.Network
|
||||||
import com.tangem.domain.tokens.model.NetworkStatus
|
import com.tangem.domain.tokens.model.NetworkStatus
|
||||||
import com.tangem.utils.converter.Converter
|
import com.tangem.utils.converter.Converter
|
||||||
|
|
@ -28,7 +29,7 @@ internal class NetworkStatusConverter(
|
||||||
address = address,
|
address = address,
|
||||||
amounts = NetworkAmountsConverter.convert(value = value.amounts),
|
amounts = NetworkAmountsConverter.convert(value = value.amounts),
|
||||||
pendingTransactions = mapOf(),
|
pendingTransactions = mapOf(),
|
||||||
isCached = isCached,
|
source = if (isCached) StatusSource.CACHE else StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is NetworkStatusDM.NoAccount -> {
|
is NetworkStatusDM.NoAccount -> {
|
||||||
|
|
@ -36,7 +37,7 @@ internal class NetworkStatusConverter(
|
||||||
address = address,
|
address = address,
|
||||||
amountToCreateAccount = value.amountToCreateAccount,
|
amountToCreateAccount = value.amountToCreateAccount,
|
||||||
errorMessage = value.errorMessage,
|
errorMessage = value.errorMessage,
|
||||||
isCached = isCached,
|
source = if (isCached) StatusSource.CACHE else StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ import com.tangem.utils.converter.Converter
|
||||||
*
|
*
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
*/
|
*/
|
||||||
internal object NetworkStatusDataModelConverter : Converter<NetworkStatus, NetworkStatusDM> {
|
internal object NetworkStatusDataModelConverter : Converter<NetworkStatus, NetworkStatusDM?> {
|
||||||
|
|
||||||
override fun convert(value: NetworkStatus): NetworkStatusDM {
|
override fun convert(value: NetworkStatus): NetworkStatusDM? {
|
||||||
return when (val status = value.value) {
|
return when (val status = value.value) {
|
||||||
is NetworkStatus.Verified -> {
|
is NetworkStatus.Verified -> {
|
||||||
NetworkStatusDM.Verified(
|
NetworkStatusDM.Verified(
|
||||||
|
|
@ -32,7 +32,7 @@ internal object NetworkStatusDataModelConverter : Converter<NetworkStatus, Netwo
|
||||||
errorMessage = status.errorMessage,
|
errorMessage = status.errorMessage,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> error("Unsupported network status: $value")
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import androidx.datastore.core.DataStore
|
||||||
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
||||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||||
import com.tangem.datasource.local.quote.converter.QuoteConverter
|
import com.tangem.datasource.local.quote.converter.QuoteConverter
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||||
import com.tangem.domain.tokens.model.Quote
|
import com.tangem.domain.tokens.model.Quote
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
|
|
@ -32,7 +33,12 @@ internal class DefaultQuotesStore(
|
||||||
|
|
||||||
runtimeStore.get()
|
runtimeStore.get()
|
||||||
.onEach {
|
.onEach {
|
||||||
val mergedQuotes = mergeQuotes(cachedQuotes = cachedQuotes, runtimeQuotes = it)
|
val mergedQuotes = mergeQuotes(
|
||||||
|
currenciesIds = currenciesIds,
|
||||||
|
cachedQuotes = cachedQuotes,
|
||||||
|
runtimeQuotes = it,
|
||||||
|
)
|
||||||
|
|
||||||
send(element = mergedQuotes)
|
send(element = mergedQuotes)
|
||||||
}
|
}
|
||||||
.launchIn(scope = this)
|
.launchIn(scope = this)
|
||||||
|
|
@ -51,6 +57,14 @@ internal class DefaultQuotesStore(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun storeEmptyQuotes(currenciesIds: Set<CryptoCurrency.RawID>) {
|
||||||
|
runtimeStore.update(default = emptySet()) { saved ->
|
||||||
|
val new = currenciesIds.map { Quote.Empty(it) }
|
||||||
|
|
||||||
|
(saved + new).distinctBy { it.rawCurrencyId }.toSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun getCachedQuotes(currenciesIds: Set<CryptoCurrency.RawID>): Set<Quote.Value> {
|
private suspend fun getCachedQuotes(currenciesIds: Set<CryptoCurrency.RawID>): Set<Quote.Value> {
|
||||||
val ids = currenciesIds.map(CryptoCurrency.RawID::value).toSet()
|
val ids = currenciesIds.map(CryptoCurrency.RawID::value).toSet()
|
||||||
val cachedQuotes = persistenceStore.data.firstOrNull().orEmpty().filterKeys { it in ids }
|
val cachedQuotes = persistenceStore.data.firstOrNull().orEmpty().filterKeys { it in ids }
|
||||||
|
|
@ -58,15 +72,27 @@ internal class DefaultQuotesStore(
|
||||||
return QuoteConverter(isCached = true).convertSet(input = cachedQuotes.entries)
|
return QuoteConverter(isCached = true).convertSet(input = cachedQuotes.entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mergeQuotes(cachedQuotes: Set<Quote.Value>, runtimeQuotes: Set<Quote>): Set<Quote> {
|
private fun mergeQuotes(
|
||||||
return runtimeQuotes.map { runtimeQuote ->
|
currenciesIds: Set<CryptoCurrency.RawID>,
|
||||||
if (runtimeQuote is Quote.Empty) {
|
cachedQuotes: Set<Quote.Value>,
|
||||||
cachedQuotes.firstOrNull { runtimeQuote.rawCurrencyId == it.rawCurrencyId } ?: runtimeQuote
|
runtimeQuotes: Set<Quote>,
|
||||||
} else {
|
): Set<Quote> {
|
||||||
runtimeQuote
|
return currenciesIds
|
||||||
|
.mapTo(hashSetOf()) { currencyId ->
|
||||||
|
val runtimeQuote = runtimeQuotes.firstOrNull { it.rawCurrencyId == currencyId }
|
||||||
|
|
||||||
|
if (runtimeQuote == null || runtimeQuote is Quote.Empty) {
|
||||||
|
getCachedQuoteIfPossible(cachedStatuses = cachedQuotes, currencyId = currencyId)
|
||||||
|
} else {
|
||||||
|
runtimeQuote
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.toSet()
|
|
||||||
|
private fun getCachedQuoteIfPossible(cachedStatuses: Set<Quote.Value>, currencyId: CryptoCurrency.RawID): Quote {
|
||||||
|
return cachedStatuses.firstOrNull { it.rawCurrencyId == currencyId }
|
||||||
|
?.copy(source = StatusSource.ONLY_CACHE)
|
||||||
|
?: Quote.Empty(currencyId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun storeInRuntimeStore(response: QuotesResponse) {
|
private suspend fun storeInRuntimeStore(response: QuotesResponse) {
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,7 @@ interface QuotesStore {
|
||||||
|
|
||||||
/** Store [response] from remote */
|
/** Store [response] from remote */
|
||||||
suspend fun store(response: QuotesResponse)
|
suspend fun store(response: QuotesResponse)
|
||||||
|
|
||||||
|
/** Store [Quote.Empty] for [currenciesIds] */
|
||||||
|
suspend fun storeEmptyQuotes(currenciesIds: Set<CryptoCurrency.RawID>)
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.datasource.local.quote.converter
|
package com.tangem.datasource.local.quote.converter
|
||||||
|
|
||||||
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||||
import com.tangem.domain.tokens.model.Quote
|
import com.tangem.domain.tokens.model.Quote
|
||||||
import com.tangem.utils.converter.Converter
|
import com.tangem.utils.converter.Converter
|
||||||
|
|
@ -23,7 +24,7 @@ internal class QuoteConverter(private val isCached: Boolean) :
|
||||||
rawCurrencyId = CryptoCurrency.RawID(currencyId),
|
rawCurrencyId = CryptoCurrency.RawID(currencyId),
|
||||||
fiatRate = quote.price.orZero(),
|
fiatRate = quote.price.orZero(),
|
||||||
priceChange = quote.priceChange24h.orZero().movePointLeft(2),
|
priceChange = quote.priceChange24h.orZero().movePointLeft(2),
|
||||||
isCached = isCached,
|
source = if (isCached) StatusSource.CACHE else StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import androidx.datastore.core.DataStore
|
||||||
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
||||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||||
import com.tangem.datasource.local.token.converter.YieldBalanceConverter
|
import com.tangem.datasource.local.token.converter.YieldBalanceConverter
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||||
import com.tangem.domain.wallets.models.UserWalletId
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
import com.tangem.utils.extensions.addOrReplace
|
import com.tangem.utils.extensions.addOrReplace
|
||||||
|
|
@ -146,16 +147,25 @@ internal class DefaultStakingBalanceStore(
|
||||||
): Set<YieldBalance> {
|
): Set<YieldBalance> {
|
||||||
return runtimeBalances
|
return runtimeBalances
|
||||||
.map { runtime ->
|
.map { runtime ->
|
||||||
if (runtime is YieldBalance.Error) {
|
runtime.takeIf { runtime !is YieldBalance.Error }
|
||||||
cachedBalances.getBalance(address = runtime.address, integrationId = runtime.integrationId)
|
?: getCachedBalanceIfPossible(cachedBalances, runtime)
|
||||||
?: runtime
|
|
||||||
} else {
|
|
||||||
runtime
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.toSet()
|
.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getCachedBalanceIfPossible(cachedBalances: Set<YieldBalance>, runtime: YieldBalance): YieldBalance {
|
||||||
|
val cached = cachedBalances.getBalance(address = runtime.address, integrationId = runtime.integrationId)
|
||||||
|
?: return runtime
|
||||||
|
|
||||||
|
val updatedCached = when (cached) {
|
||||||
|
is YieldBalance.Data -> cached.copy(source = StatusSource.ONLY_CACHE)
|
||||||
|
is YieldBalance.Empty -> cached.copy(source = StatusSource.ONLY_CACHE)
|
||||||
|
is YieldBalance.Error -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedCached ?: runtime
|
||||||
|
}
|
||||||
|
|
||||||
private fun Set<YieldBalance>.getBalance(address: String?, integrationId: String?): YieldBalance? {
|
private fun Set<YieldBalance>.getBalance(address: String?, integrationId: String?): YieldBalance? {
|
||||||
return firstOrNull { yieldBalance ->
|
return firstOrNull { yieldBalance ->
|
||||||
val data = yieldBalance as? YieldBalance.Data
|
val data = yieldBalance as? YieldBalance.Data
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.datasource.local.token.converter
|
package com.tangem.datasource.local.token.converter
|
||||||
|
|
||||||
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.staking.model.stakekit.BalanceItem
|
import com.tangem.domain.staking.model.stakekit.BalanceItem
|
||||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||||
import com.tangem.domain.staking.model.stakekit.YieldBalanceItem
|
import com.tangem.domain.staking.model.stakekit.YieldBalanceItem
|
||||||
|
|
@ -13,7 +14,7 @@ internal class YieldBalanceConverter(private val isCached: Boolean) : Converter<
|
||||||
YieldBalance.Empty(
|
YieldBalance.Empty(
|
||||||
integrationId = value.integrationId,
|
integrationId = value.integrationId,
|
||||||
address = value.addresses.address,
|
address = value.addresses.address,
|
||||||
isCached = isCached,
|
source = if (isCached) StatusSource.CACHE else StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
YieldBalance.Data(
|
YieldBalance.Data(
|
||||||
|
|
@ -39,7 +40,7 @@ internal class YieldBalanceConverter(private val isCached: Boolean) : Converter<
|
||||||
.sortedWith(compareBy({ it.type }, { it.amount })),
|
.sortedWith(compareBy({ it.type }, { it.amount })),
|
||||||
integrationId = value.integrationId,
|
integrationId = value.integrationId,
|
||||||
),
|
),
|
||||||
isCached = isCached,
|
source = if (isCached) StatusSource.CACHE else StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||||
import com.tangem.data.common.currency.CryptoCurrencyFactory
|
import com.tangem.data.common.currency.CryptoCurrencyFactory
|
||||||
import com.tangem.data.common.currency.getNetwork
|
import com.tangem.data.common.currency.getNetwork
|
||||||
import com.tangem.datasource.api.tangemTech.models.HotCryptoResponse
|
import com.tangem.datasource.api.tangemTech.models.HotCryptoResponse
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
import com.tangem.domain.onramp.model.HotCryptoCurrency
|
import com.tangem.domain.onramp.model.HotCryptoCurrency
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||||
|
|
@ -94,7 +95,7 @@ internal class HotCryptoCurrencyConverter(
|
||||||
rawCurrencyId = rawCurrencyId,
|
rawCurrencyId = rawCurrencyId,
|
||||||
fiatRate = fiatRate,
|
fiatRate = fiatRate,
|
||||||
priceChange = priceChange.movePointLeft(2),
|
priceChange = priceChange.movePointLeft(2),
|
||||||
isCached = false, // It doesn't matter
|
source = StatusSource.ACTUAL, // It doesn't matter
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Quote.Empty(rawCurrencyId)
|
Quote.Empty(rawCurrencyId)
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ internal class DefaultQuotesRepository(
|
||||||
},
|
},
|
||||||
onError = { error ->
|
onError = { error ->
|
||||||
cacheRegistry.invalidate(rawCurrenciesIds.map { getQuoteCacheKey(it) })
|
cacheRegistry.invalidate(rawCurrenciesIds.map { getQuoteCacheKey(it) })
|
||||||
|
quotesStore.storeEmptyQuotes(currenciesIds = rawCurrenciesIds)
|
||||||
|
|
||||||
throw error
|
throw error
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.data.tokens.utils
|
package com.tangem.data.tokens.utils
|
||||||
|
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.tokens.model.*
|
import com.tangem.domain.tokens.model.*
|
||||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||||
import com.tangem.domain.walletmanager.model.Address
|
import com.tangem.domain.walletmanager.model.Address
|
||||||
|
|
@ -26,7 +27,7 @@ internal class NetworkStatusFactory {
|
||||||
address = getNetworkAddress(result.selectedAddress, result.addresses),
|
address = getNetworkAddress(result.selectedAddress, result.addresses),
|
||||||
amountToCreateAccount = result.amountToCreateAccount,
|
amountToCreateAccount = result.amountToCreateAccount,
|
||||||
errorMessage = result.errorMessage,
|
errorMessage = result.errorMessage,
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
is UpdateWalletManagerResult.Verified -> NetworkStatus.Verified(
|
is UpdateWalletManagerResult.Verified -> NetworkStatus.Verified(
|
||||||
address = getNetworkAddress(result.selectedAddress, result.addresses),
|
address = getNetworkAddress(result.selectedAddress, result.addresses),
|
||||||
|
|
@ -35,7 +36,7 @@ internal class NetworkStatusFactory {
|
||||||
transactions = result.currentTransactions,
|
transactions = result.currentTransactions,
|
||||||
currencies = currencies,
|
currencies = currencies,
|
||||||
),
|
),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.tangem.domain.models
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Source of the status of any loaded data
|
||||||
|
*
|
||||||
|
[REDACTED_AUTHOR]
|
||||||
|
*/
|
||||||
|
enum class StatusSource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status is loaded from the cache.
|
||||||
|
* In most cases, it's a temporary value, then the source should become either [ACTUAL] or [ONLY_CACHE]
|
||||||
|
*/
|
||||||
|
CACHE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status is updated by a data source that is of actual value.
|
||||||
|
* In most cases, this is a remote data source. But it can also be a value that we have updated programmatically.
|
||||||
|
*/
|
||||||
|
ACTUAL,
|
||||||
|
|
||||||
|
/** Status is loaded from the cache and can't be updated with actual value */
|
||||||
|
ONLY_CACHE,
|
||||||
|
}
|
||||||
|
|
@ -9,6 +9,7 @@ plugins {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(projects.domain.core)
|
implementation(projects.domain.core)
|
||||||
|
implementation(projects.domain.models)
|
||||||
|
|
||||||
implementation(deps.kotlin.serialization)
|
implementation(deps.kotlin.serialization)
|
||||||
implementation(deps.jodatime)
|
implementation(deps.jodatime)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.domain.staking.model.stakekit
|
package com.tangem.domain.staking.model.stakekit
|
||||||
|
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionType
|
import com.tangem.domain.staking.model.stakekit.action.StakingActionType
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
@ -13,7 +14,7 @@ sealed class YieldBalance {
|
||||||
override val integrationId: String?,
|
override val integrationId: String?,
|
||||||
override val address: String,
|
override val address: String,
|
||||||
val balance: YieldBalanceItem,
|
val balance: YieldBalanceItem,
|
||||||
val isCached: Boolean,
|
val source: StatusSource,
|
||||||
) : YieldBalance() {
|
) : YieldBalance() {
|
||||||
fun getTotalWithRewardsStakingBalance(): BigDecimal {
|
fun getTotalWithRewardsStakingBalance(): BigDecimal {
|
||||||
return balance.items.sumOf { it.amount }
|
return balance.items.sumOf { it.amount }
|
||||||
|
|
@ -42,7 +43,7 @@ sealed class YieldBalance {
|
||||||
data class Empty(
|
data class Empty(
|
||||||
override val integrationId: String?,
|
override val integrationId: String?,
|
||||||
override val address: String,
|
override val address: String,
|
||||||
val isCached: Boolean,
|
val source: StatusSource,
|
||||||
) : YieldBalance()
|
) : YieldBalance()
|
||||||
|
|
||||||
data class Error(override val integrationId: String?, override val address: String?) : YieldBalance()
|
data class Error(override val integrationId: String?, override val address: String?) : YieldBalance()
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ dependencies {
|
||||||
implementation(projects.core.analytics.models)
|
implementation(projects.core.analytics.models)
|
||||||
|
|
||||||
/** Project - Domain */
|
/** Project - Domain */
|
||||||
|
implementation(projects.domain.models)
|
||||||
implementation(projects.domain.txhistory.models)
|
implementation(projects.domain.txhistory.models)
|
||||||
implementation(projects.domain.staking.models)
|
implementation(projects.domain.staking.models)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.domain.tokens.model
|
package com.tangem.domain.tokens.model
|
||||||
|
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
@ -83,6 +84,7 @@ data class CryptoCurrencyStatus(
|
||||||
* Represents a state where there is no account associated with the cryptocurrency
|
* Represents a state where there is no account associated with the cryptocurrency
|
||||||
*
|
*
|
||||||
* @property amountToCreateAccount base reserve amount for account creation
|
* @property amountToCreateAccount base reserve amount for account creation
|
||||||
|
* @property source source of data
|
||||||
*/
|
*/
|
||||||
data class NoAccount(
|
data class NoAccount(
|
||||||
val amountToCreateAccount: BigDecimal,
|
val amountToCreateAccount: BigDecimal,
|
||||||
|
|
@ -90,6 +92,7 @@ data class CryptoCurrencyStatus(
|
||||||
override val priceChange: BigDecimal?,
|
override val priceChange: BigDecimal?,
|
||||||
override val fiatRate: BigDecimal?,
|
override val fiatRate: BigDecimal?,
|
||||||
override val networkAddress: NetworkAddress,
|
override val networkAddress: NetworkAddress,
|
||||||
|
val source: StatusSource,
|
||||||
) : Value(isError = false) {
|
) : Value(isError = false) {
|
||||||
|
|
||||||
override val amount: BigDecimal = BigDecimal.ZERO
|
override val amount: BigDecimal = BigDecimal.ZERO
|
||||||
|
|
@ -105,6 +108,7 @@ data class CryptoCurrencyStatus(
|
||||||
* @property hasCurrentNetworkTransactions Indicates if there are any transactions in progress related to the
|
* @property hasCurrentNetworkTransactions Indicates if there are any transactions in progress related to the
|
||||||
* cryptocurrency network.
|
* cryptocurrency network.
|
||||||
* @property pendingTransactions The current cryptocurrency transactions.
|
* @property pendingTransactions The current cryptocurrency transactions.
|
||||||
|
* @property source source of data
|
||||||
*/
|
*/
|
||||||
data class Loaded(
|
data class Loaded(
|
||||||
override val amount: BigDecimal,
|
override val amount: BigDecimal,
|
||||||
|
|
@ -115,6 +119,7 @@ data class CryptoCurrencyStatus(
|
||||||
override val hasCurrentNetworkTransactions: Boolean,
|
override val hasCurrentNetworkTransactions: Boolean,
|
||||||
override val pendingTransactions: Set<TxHistoryItem>,
|
override val pendingTransactions: Set<TxHistoryItem>,
|
||||||
override val networkAddress: NetworkAddress,
|
override val networkAddress: NetworkAddress,
|
||||||
|
val source: StatusSource,
|
||||||
) : Value(isError = false)
|
) : Value(isError = false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.domain.tokens.model
|
package com.tangem.domain.tokens.model
|
||||||
|
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
|
@ -21,14 +22,14 @@ data class NetworkStatus(
|
||||||
*/
|
*/
|
||||||
sealed class Value {
|
sealed class Value {
|
||||||
|
|
||||||
abstract val isCached: Boolean
|
abstract val source: StatusSource
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the state where the network is refreshing.
|
* Represents the state where the network is refreshing.
|
||||||
*/
|
*/
|
||||||
data object Refreshing : Value() {
|
data object Refreshing : Value() {
|
||||||
override val isCached: Boolean = false
|
override val source: StatusSource = StatusSource.ACTUAL
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -37,14 +38,14 @@ data class NetworkStatus(
|
||||||
* @property address Network addresses.
|
* @property address Network addresses.
|
||||||
*/
|
*/
|
||||||
data class Unreachable(val address: NetworkAddress?) : Value() {
|
data class Unreachable(val address: NetworkAddress?) : Value() {
|
||||||
override val isCached: Boolean = false
|
override val source: StatusSource = StatusSource.ACTUAL
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the state where a derivation has been missed.
|
* Represents the state where a derivation has been missed.
|
||||||
*/
|
*/
|
||||||
data object MissedDerivation : Value() {
|
data object MissedDerivation : Value() {
|
||||||
override val isCached: Boolean = false
|
override val source: StatusSource = StatusSource.ACTUAL
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -54,14 +55,14 @@ data class NetworkStatus(
|
||||||
* @property address Network addresses.
|
* @property address Network addresses.
|
||||||
* @property amounts A map containing the amounts associated with different cryptocurrencies within the network.
|
* @property amounts A map containing the amounts associated with different cryptocurrencies within the network.
|
||||||
* @property pendingTransactions A map containing pending transactions associated with different cryptocurrencies
|
* @property pendingTransactions A map containing pending transactions associated with different cryptocurrencies
|
||||||
* @property isCached flag that determines whether the status is a cache
|
* @property source source of data
|
||||||
* within the network.
|
* within the network.
|
||||||
*/
|
*/
|
||||||
data class Verified(
|
data class Verified(
|
||||||
val address: NetworkAddress,
|
val address: NetworkAddress,
|
||||||
val amounts: Map<CryptoCurrency.ID, CryptoCurrencyAmountStatus>,
|
val amounts: Map<CryptoCurrency.ID, CryptoCurrencyAmountStatus>,
|
||||||
val pendingTransactions: Map<CryptoCurrency.ID, Set<TxHistoryItem>>,
|
val pendingTransactions: Map<CryptoCurrency.ID, Set<TxHistoryItem>>,
|
||||||
override val isCached: Boolean,
|
override val source: StatusSource,
|
||||||
) : Value()
|
) : Value()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -70,12 +71,12 @@ data class NetworkStatus(
|
||||||
* @property address Network addresses.
|
* @property address Network addresses.
|
||||||
* @property amountToCreateAccount The amount required to create an account within the network.
|
* @property amountToCreateAccount The amount required to create an account within the network.
|
||||||
* @property errorMessage error message
|
* @property errorMessage error message
|
||||||
* @property isCached flag that determines whether the status is a cache
|
* @property source source of data
|
||||||
*/
|
*/
|
||||||
data class NoAccount(
|
data class NoAccount(
|
||||||
val address: NetworkAddress,
|
val address: NetworkAddress,
|
||||||
val amountToCreateAccount: BigDecimal,
|
val amountToCreateAccount: BigDecimal,
|
||||||
val errorMessage: String,
|
val errorMessage: String,
|
||||||
override val isCached: Boolean,
|
override val source: StatusSource,
|
||||||
) : Value()
|
) : Value()
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.domain.tokens.model
|
package com.tangem.domain.tokens.model
|
||||||
|
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
sealed interface Quote {
|
sealed interface Quote {
|
||||||
|
|
@ -19,12 +20,12 @@ sealed interface Quote {
|
||||||
* @property rawCurrencyId The unique identifier of the cryptocurrency for which the financial information is provided.
|
* @property rawCurrencyId The unique identifier of the cryptocurrency for which the financial information is provided.
|
||||||
* @property fiatRate The current fiat exchange rate for the cryptocurrency.
|
* @property fiatRate The current fiat exchange rate for the cryptocurrency.
|
||||||
* @property priceChange The price change for the cryptocurrency.
|
* @property priceChange The price change for the cryptocurrency.
|
||||||
* @property isCached flag that determines whether the quote is a cache
|
* @property source source of data
|
||||||
*/
|
*/
|
||||||
data class Value(
|
data class Value(
|
||||||
override val rawCurrencyId: CryptoCurrency.RawID,
|
override val rawCurrencyId: CryptoCurrency.RawID,
|
||||||
val fiatRate: BigDecimal,
|
val fiatRate: BigDecimal,
|
||||||
val priceChange: BigDecimal,
|
val priceChange: BigDecimal,
|
||||||
val isCached: Boolean,
|
val source: StatusSource,
|
||||||
) : Quote
|
) : Quote
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.domain.tokens.operations
|
package com.tangem.domain.tokens.operations
|
||||||
|
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||||
import com.tangem.domain.tokens.model.*
|
import com.tangem.domain.tokens.model.*
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
@ -49,17 +50,27 @@ internal class CurrencyStatusOperations(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createNoAccountStatus(status: NetworkStatus.NoAccount): CryptoCurrencyStatus.NoAccount =
|
private fun createNoAccountStatus(status: NetworkStatus.NoAccount): CryptoCurrencyStatus.NoAccount {
|
||||||
CryptoCurrencyStatus.NoAccount(
|
return CryptoCurrencyStatus.NoAccount(
|
||||||
amountToCreateAccount = status.amountToCreateAccount,
|
amountToCreateAccount = status.amountToCreateAccount,
|
||||||
fiatAmount = if (quote == null) null else BigDecimal.ZERO,
|
fiatAmount = if (quote == null) null else BigDecimal.ZERO,
|
||||||
priceChange = quote?.priceChange,
|
priceChange = quote?.priceChange,
|
||||||
fiatRate = quote?.fiatRate,
|
fiatRate = quote?.fiatRate,
|
||||||
networkAddress = status.address,
|
networkAddress = status.address,
|
||||||
|
source = getResultStatusSource(
|
||||||
|
sources = listOf(
|
||||||
|
status.source,
|
||||||
|
(quote as? Quote.Value)?.source ?: StatusSource.ACTUAL,
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun createStatus(status: NetworkStatus.Verified, yieldBalance: YieldBalance?): CryptoCurrencyStatus.Value {
|
private fun createStatus(
|
||||||
val amount = when (val amount = status.amounts[currency.id]) {
|
networkStatusValue: NetworkStatus.Verified,
|
||||||
|
yieldBalance: YieldBalance?,
|
||||||
|
): CryptoCurrencyStatus.Value {
|
||||||
|
val amount = when (val amount = networkStatusValue.amounts[currency.id]) {
|
||||||
null -> {
|
null -> {
|
||||||
return CryptoCurrencyStatus.Loading
|
return CryptoCurrencyStatus.Loading
|
||||||
}
|
}
|
||||||
|
|
@ -69,10 +80,10 @@ internal class CurrencyStatusOperations(
|
||||||
is CryptoCurrencyAmountStatus.Loaded -> amount.value
|
is CryptoCurrencyAmountStatus.Loaded -> amount.value
|
||||||
}
|
}
|
||||||
|
|
||||||
val hasCurrentNetworkTransactions = status.pendingTransactions.isNotEmpty()
|
val hasCurrentNetworkTransactions = networkStatusValue.pendingTransactions.isNotEmpty()
|
||||||
val currentTransactions = status.pendingTransactions.getOrElse(currency.id, ::emptySet)
|
val currentTransactions = networkStatusValue.pendingTransactions.getOrElse(currency.id, ::emptySet)
|
||||||
val yieldBalanceData = yieldBalance as? YieldBalance.Data
|
val yieldBalanceData = yieldBalance as? YieldBalance.Data
|
||||||
val isCurrentAddressStaking = yieldBalanceData?.address == status.address.defaultAddress.value
|
val isCurrentAddressStaking = yieldBalanceData?.address == networkStatusValue.address.defaultAddress.value
|
||||||
val filteredTokenBalances = yieldBalanceData?.balance?.items?.filter {
|
val filteredTokenBalances = yieldBalanceData?.balance?.items?.filter {
|
||||||
it.token.coinGeckoId == currency.id.rawCurrencyId?.value
|
it.token.coinGeckoId == currency.id.rawCurrencyId?.value
|
||||||
}
|
}
|
||||||
|
|
@ -94,14 +105,14 @@ internal class CurrencyStatusOperations(
|
||||||
priceChange = quote?.priceChange,
|
priceChange = quote?.priceChange,
|
||||||
hasCurrentNetworkTransactions = hasCurrentNetworkTransactions,
|
hasCurrentNetworkTransactions = hasCurrentNetworkTransactions,
|
||||||
pendingTransactions = currentTransactions,
|
pendingTransactions = currentTransactions,
|
||||||
networkAddress = status.address,
|
networkAddress = networkStatusValue.address,
|
||||||
yieldBalance = currentYieldBalance,
|
yieldBalance = currentYieldBalance,
|
||||||
)
|
)
|
||||||
quote is Quote.Empty || ignoreQuote -> CryptoCurrencyStatus.NoQuote(
|
quote is Quote.Empty || ignoreQuote -> CryptoCurrencyStatus.NoQuote(
|
||||||
amount = amount,
|
amount = amount,
|
||||||
hasCurrentNetworkTransactions = hasCurrentNetworkTransactions,
|
hasCurrentNetworkTransactions = hasCurrentNetworkTransactions,
|
||||||
pendingTransactions = currentTransactions,
|
pendingTransactions = currentTransactions,
|
||||||
networkAddress = status.address,
|
networkAddress = networkStatusValue.address,
|
||||||
yieldBalance = currentYieldBalance,
|
yieldBalance = currentYieldBalance,
|
||||||
)
|
)
|
||||||
quote is Quote.Value -> CryptoCurrencyStatus.Loaded(
|
quote is Quote.Value -> CryptoCurrencyStatus.Loaded(
|
||||||
|
|
@ -111,8 +122,15 @@ internal class CurrencyStatusOperations(
|
||||||
priceChange = quote.priceChange,
|
priceChange = quote.priceChange,
|
||||||
hasCurrentNetworkTransactions = hasCurrentNetworkTransactions,
|
hasCurrentNetworkTransactions = hasCurrentNetworkTransactions,
|
||||||
pendingTransactions = currentTransactions,
|
pendingTransactions = currentTransactions,
|
||||||
networkAddress = status.address,
|
networkAddress = networkStatusValue.address,
|
||||||
yieldBalance = currentYieldBalance,
|
yieldBalance = currentYieldBalance,
|
||||||
|
source = getResultStatusSource(
|
||||||
|
sources = listOf(
|
||||||
|
networkStatusValue.source,
|
||||||
|
currentYieldBalance?.source ?: StatusSource.ACTUAL,
|
||||||
|
quote.source,
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
else -> CryptoCurrencyStatus.Loading
|
else -> CryptoCurrencyStatus.Loading
|
||||||
}
|
}
|
||||||
|
|
@ -127,4 +145,18 @@ internal class CurrencyStatusOperations(
|
||||||
private fun calculateFiatAmount(amount: BigDecimal, fiatRate: BigDecimal): BigDecimal {
|
private fun calculateFiatAmount(amount: BigDecimal, fiatRate: BigDecimal): BigDecimal {
|
||||||
return amount * fiatRate
|
return amount * fiatRate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ACTUAL, ACTUAL, ACTUAL -> ACTUAL
|
||||||
|
* ACTUAL, ACTUAL, CACHE -> CACHE
|
||||||
|
* ACTUAL, ACTUAL, ONLY_CACHE -> ONLY_CACHE
|
||||||
|
* ACTUAL, CACHE, ONLY_CACHE -> ONLY_CACHE
|
||||||
|
*/
|
||||||
|
private fun getResultStatusSource(sources: List<StatusSource>): StatusSource {
|
||||||
|
return when {
|
||||||
|
sources.any { it == StatusSource.ONLY_CACHE } -> StatusSource.ONLY_CACHE
|
||||||
|
sources.any { it == StatusSource.CACHE } -> StatusSource.CACHE
|
||||||
|
else -> StatusSource.ACTUAL
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package com.tangem.domain.tokens.mock
|
||||||
|
|
||||||
import arrow.core.NonEmptySet
|
import arrow.core.NonEmptySet
|
||||||
import arrow.core.nonEmptySetOf
|
import arrow.core.nonEmptySetOf
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrencyAmountStatus
|
import com.tangem.domain.tokens.model.CryptoCurrencyAmountStatus
|
||||||
import com.tangem.domain.tokens.model.Network
|
import com.tangem.domain.tokens.model.Network
|
||||||
import com.tangem.domain.tokens.model.NetworkAddress
|
import com.tangem.domain.tokens.model.NetworkAddress
|
||||||
|
|
@ -76,7 +77,7 @@ internal object MockNetworks {
|
||||||
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
||||||
),
|
),
|
||||||
errorMessage = "",
|
errorMessage = "",
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -92,7 +93,7 @@ internal object MockNetworks {
|
||||||
address = NetworkAddress.Single(
|
address = NetworkAddress.Single(
|
||||||
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
||||||
),
|
),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -108,7 +109,7 @@ internal object MockNetworks {
|
||||||
address = NetworkAddress.Single(
|
address = NetworkAddress.Single(
|
||||||
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
||||||
),
|
),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -125,7 +126,7 @@ internal object MockNetworks {
|
||||||
address = NetworkAddress.Single(
|
address = NetworkAddress.Single(
|
||||||
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
||||||
),
|
),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.domain.tokens.mock
|
package com.tangem.domain.tokens.mock
|
||||||
|
|
||||||
import arrow.core.nonEmptySetOf
|
import arrow.core.nonEmptySetOf
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||||
import com.tangem.domain.tokens.model.Quote
|
import com.tangem.domain.tokens.model.Quote
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
@ -12,70 +13,70 @@ internal object MockQuotes {
|
||||||
rawCurrencyId = MockTokens.token1.id.rawCurrencyId!!,
|
rawCurrencyId = MockTokens.token1.id.rawCurrencyId!!,
|
||||||
fiatRate = BigDecimal("1.23"),
|
fiatRate = BigDecimal("1.23"),
|
||||||
priceChange = BigDecimal("0.01"),
|
priceChange = BigDecimal("0.01"),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
val quote2 = Quote.Value(
|
val quote2 = Quote.Value(
|
||||||
rawCurrencyId = MockTokens.token2.id.rawCurrencyId!!,
|
rawCurrencyId = MockTokens.token2.id.rawCurrencyId!!,
|
||||||
fiatRate = BigDecimal("2.34"),
|
fiatRate = BigDecimal("2.34"),
|
||||||
priceChange = BigDecimal("-0.02"),
|
priceChange = BigDecimal("-0.02"),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
val quote3 = Quote.Value(
|
val quote3 = Quote.Value(
|
||||||
rawCurrencyId = MockTokens.token3.id.rawCurrencyId!!,
|
rawCurrencyId = MockTokens.token3.id.rawCurrencyId!!,
|
||||||
fiatRate = BigDecimal("3.45"),
|
fiatRate = BigDecimal("3.45"),
|
||||||
priceChange = BigDecimal("0.03"),
|
priceChange = BigDecimal("0.03"),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
val quote4 = Quote.Value(
|
val quote4 = Quote.Value(
|
||||||
rawCurrencyId = MockTokens.token4.id.rawCurrencyId!!,
|
rawCurrencyId = MockTokens.token4.id.rawCurrencyId!!,
|
||||||
fiatRate = BigDecimal("4.56"),
|
fiatRate = BigDecimal("4.56"),
|
||||||
priceChange = BigDecimal("-0.04"),
|
priceChange = BigDecimal("-0.04"),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
val quote5 = Quote.Value(
|
val quote5 = Quote.Value(
|
||||||
rawCurrencyId = MockTokens.token5.id.rawCurrencyId!!,
|
rawCurrencyId = MockTokens.token5.id.rawCurrencyId!!,
|
||||||
fiatRate = BigDecimal("5.67"),
|
fiatRate = BigDecimal("5.67"),
|
||||||
priceChange = BigDecimal("0.05"),
|
priceChange = BigDecimal("0.05"),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
val quote6 = Quote.Value(
|
val quote6 = Quote.Value(
|
||||||
rawCurrencyId = MockTokens.token6.id.rawCurrencyId!!,
|
rawCurrencyId = MockTokens.token6.id.rawCurrencyId!!,
|
||||||
fiatRate = BigDecimal("6.78"),
|
fiatRate = BigDecimal("6.78"),
|
||||||
priceChange = BigDecimal("-0.06"),
|
priceChange = BigDecimal("-0.06"),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
val quote7 = Quote.Value(
|
val quote7 = Quote.Value(
|
||||||
rawCurrencyId = MockTokens.token7.id.rawCurrencyId!!,
|
rawCurrencyId = MockTokens.token7.id.rawCurrencyId!!,
|
||||||
fiatRate = BigDecimal("7.89"),
|
fiatRate = BigDecimal("7.89"),
|
||||||
priceChange = BigDecimal("0.07"),
|
priceChange = BigDecimal("0.07"),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
val quote8 = Quote.Value(
|
val quote8 = Quote.Value(
|
||||||
rawCurrencyId = MockTokens.token8.id.rawCurrencyId!!,
|
rawCurrencyId = MockTokens.token8.id.rawCurrencyId!!,
|
||||||
fiatRate = BigDecimal("8.90"),
|
fiatRate = BigDecimal("8.90"),
|
||||||
priceChange = BigDecimal("-0.08"),
|
priceChange = BigDecimal("-0.08"),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
val quote9 = Quote.Value(
|
val quote9 = Quote.Value(
|
||||||
rawCurrencyId = MockTokens.token9.id.rawCurrencyId!!,
|
rawCurrencyId = MockTokens.token9.id.rawCurrencyId!!,
|
||||||
fiatRate = BigDecimal("9.01"),
|
fiatRate = BigDecimal("9.01"),
|
||||||
priceChange = BigDecimal("0.09"),
|
priceChange = BigDecimal("0.09"),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
val quote10 = Quote.Value(
|
val quote10 = Quote.Value(
|
||||||
rawCurrencyId = MockTokens.token10.id.rawCurrencyId!!,
|
rawCurrencyId = MockTokens.token10.id.rawCurrencyId!!,
|
||||||
fiatRate = BigDecimal("10.12"),
|
fiatRate = BigDecimal("10.12"),
|
||||||
priceChange = BigDecimal("-0.10"),
|
priceChange = BigDecimal("-0.10"),
|
||||||
isCached = false,
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
val quote11 = Quote.Empty(CryptoCurrency.RawID("null"))
|
val quote11 = Quote.Empty(CryptoCurrency.RawID("null"))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.domain.tokens.mock
|
package com.tangem.domain.tokens.mock
|
||||||
|
|
||||||
import arrow.core.nonEmptyListOf
|
import arrow.core.nonEmptyListOf
|
||||||
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.tokens.model.*
|
import com.tangem.domain.tokens.model.*
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
|
@ -74,6 +75,7 @@ internal object MockTokensStates {
|
||||||
networkAddress = NetworkAddress.Single(
|
networkAddress = NetworkAddress.Single(
|
||||||
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
||||||
),
|
),
|
||||||
|
source = StatusSource.ACTUAL,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -87,6 +89,7 @@ internal object MockTokensStates {
|
||||||
networkAddress = NetworkAddress.Single(
|
networkAddress = NetworkAddress.Single(
|
||||||
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
||||||
),
|
),
|
||||||
|
source = StatusSource.ACTUAL,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -100,6 +103,7 @@ internal object MockTokensStates {
|
||||||
networkAddress = NetworkAddress.Single(
|
networkAddress = NetworkAddress.Single(
|
||||||
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
||||||
),
|
),
|
||||||
|
source = StatusSource.ACTUAL,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -113,6 +117,7 @@ internal object MockTokensStates {
|
||||||
networkAddress = NetworkAddress.Single(
|
networkAddress = NetworkAddress.Single(
|
||||||
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary),
|
||||||
),
|
),
|
||||||
|
source = StatusSource.ACTUAL,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -157,6 +162,7 @@ internal object MockTokensStates {
|
||||||
hasCurrentNetworkTransactions = false,
|
hasCurrentNetworkTransactions = false,
|
||||||
networkAddress = requireNotNull(networkStatus.value as? NetworkStatus.Verified).address,
|
networkAddress = requireNotNull(networkStatus.value as? NetworkStatus.Verified).address,
|
||||||
yieldBalance = null,
|
yieldBalance = null,
|
||||||
|
source = StatusSource.ACTUAL,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
status.copy(value = value)
|
status.copy(value = value)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue