Updated on 2026-08-14
This commit is contained in:
parent
f089d31106
commit
eda6a624d0
26 changed files with 161 additions and 277 deletions
|
|
@ -51,10 +51,9 @@ internal object TokensDomainModule {
|
|||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideToggleTokenListGroupingUseCase(
|
||||
networksRepository: NetworksRepository,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): ToggleTokenListGroupingUseCase {
|
||||
return ToggleTokenListGroupingUseCase(networksRepository, dispatchers)
|
||||
return ToggleTokenListGroupingUseCase(dispatchers)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import com.tangem.tap.features.wallet.models.Currency
|
|||
import com.tangem.tap.store
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
class CryptoCurrencyConverter : Converter<Currency, CryptoCurrency> {
|
||||
internal class CryptoCurrencyConverter : Converter<Currency, CryptoCurrency> {
|
||||
|
||||
private val cryptoCurrencyFactory by lazy { CryptoCurrencyFactory() }
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ internal class DefaultNetworksRepository(
|
|||
private suspend fun fetchNetworkStatus(userWalletId: UserWalletId, networkId: Network.ID) {
|
||||
val currencies = getCurrencies(userWalletId)
|
||||
.asSequence()
|
||||
.filter { it.networkId == networkId }
|
||||
.filter { it.network.id == networkId }
|
||||
|
||||
val result = walletManagersFacade.update(
|
||||
userWalletId = userWalletId,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
package com.tangem.data.tokens.utils
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Token as SdkToken
|
||||
import com.tangem.domain.common.DerivationStyleProvider
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import timber.log.Timber
|
||||
import com.tangem.blockchain.common.Token as SdkToken
|
||||
|
||||
// FIXME: Make internal
|
||||
class CryptoCurrencyFactory {
|
||||
|
||||
fun createToken(
|
||||
|
|
@ -19,9 +20,10 @@ class CryptoCurrencyFactory {
|
|||
}
|
||||
|
||||
val id = getTokenId(blockchain, sdkToken)
|
||||
|
||||
return CryptoCurrency.Token(
|
||||
id = id,
|
||||
networkId = getNetworkId(blockchain),
|
||||
network = getNetwork(blockchain) ?: return null,
|
||||
name = sdkToken.name,
|
||||
symbol = sdkToken.symbol,
|
||||
iconUrl = getTokenIconUrl(blockchain, sdkToken),
|
||||
|
|
@ -29,8 +31,6 @@ class CryptoCurrencyFactory {
|
|||
isCustom = isCustomToken(id),
|
||||
contractAddress = sdkToken.contractAddress,
|
||||
derivationPath = getDerivationPath(blockchain, derivationStyleProvider),
|
||||
blockchainName = blockchain.fullName,
|
||||
standardType = getTokenStandardType(blockchain, sdkToken),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ class CryptoCurrencyFactory {
|
|||
|
||||
return CryptoCurrency.Coin(
|
||||
id = getCoinId(blockchain),
|
||||
networkId = getNetworkId(blockchain),
|
||||
network = getNetwork(blockchain) ?: return null,
|
||||
name = blockchain.fullName,
|
||||
symbol = blockchain.currency,
|
||||
iconUrl = getCoinIconUrl(blockchain),
|
||||
|
|
|
|||
|
|
@ -3,22 +3,13 @@ package com.tangem.data.tokens.utils
|
|||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.utils.converter.Converter
|
||||
import timber.log.Timber
|
||||
|
||||
internal class NetworkConverter : Converter<Network.ID, Network?> {
|
||||
|
||||
override fun convert(value: Network.ID): Network? {
|
||||
val blockchain = Blockchain.fromId(value.value)
|
||||
|
||||
if (blockchain == Blockchain.Unknown) {
|
||||
Timber.e("Unable to convert Unknown blockchain to the domain network model")
|
||||
return null
|
||||
}
|
||||
|
||||
return Network(
|
||||
id = value,
|
||||
name = blockchain.fullName,
|
||||
)
|
||||
return getNetwork(blockchain)
|
||||
}
|
||||
|
||||
override fun convertList(input: Collection<Network.ID>): List<Network> {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
package com.tangem.data.tokens.utils
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import timber.log.Timber
|
||||
|
||||
internal fun getNetwork(blockchain: Blockchain): Network? {
|
||||
if (blockchain == Blockchain.Unknown) {
|
||||
Timber.e("Unable to convert Unknown blockchain to the domain network model")
|
||||
return null
|
||||
}
|
||||
|
||||
return Network(
|
||||
id = Network.ID(blockchain.id),
|
||||
name = blockchain.fullName,
|
||||
isTestnet = blockchain.isTestnet(),
|
||||
standardType = getNetworkStandardType(blockchain),
|
||||
)
|
||||
}
|
||||
|
||||
private fun getNetworkStandardType(blockchain: Blockchain): Network.StandardType {
|
||||
return when (blockchain) {
|
||||
Blockchain.Ethereum, Blockchain.EthereumTestnet -> Network.StandardType.ERC20
|
||||
Blockchain.BSC, Blockchain.BSCTestnet -> Network.StandardType.BEP20
|
||||
Blockchain.Binance, Blockchain.BinanceTestnet -> Network.StandardType.BEP2
|
||||
Blockchain.Tron, Blockchain.TronTestnet -> Network.StandardType.TRC20
|
||||
else -> Network.StandardType.Unspecified(blockchain.name)
|
||||
}
|
||||
}
|
||||
|
|
@ -59,10 +59,10 @@ internal class ResponseCurrenciesFactory(private val demoConfig: DemoConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
private fun createCoin(blockchain: Blockchain, responseToken: UserTokensResponse.Token): CryptoCurrency.Coin {
|
||||
private fun createCoin(blockchain: Blockchain, responseToken: UserTokensResponse.Token): CryptoCurrency.Coin? {
|
||||
return CryptoCurrency.Coin(
|
||||
id = getCoinId(blockchain),
|
||||
networkId = getNetworkId(blockchain),
|
||||
network = getNetwork(blockchain) ?: return null,
|
||||
name = responseToken.name,
|
||||
symbol = responseToken.symbol,
|
||||
decimals = responseToken.decimals,
|
||||
|
|
@ -71,12 +71,12 @@ internal class ResponseCurrenciesFactory(private val demoConfig: DemoConfig) {
|
|||
)
|
||||
}
|
||||
|
||||
private fun createToken(blockchain: Blockchain, sdkToken: Token, derivationPath: String?): CryptoCurrency.Token {
|
||||
private fun createToken(blockchain: Blockchain, sdkToken: Token, derivationPath: String?): CryptoCurrency.Token? {
|
||||
val id = getTokenId(blockchain, sdkToken)
|
||||
|
||||
return CryptoCurrency.Token(
|
||||
id = id,
|
||||
networkId = getNetworkId(blockchain),
|
||||
network = getNetwork(blockchain) ?: return null,
|
||||
name = sdkToken.name,
|
||||
symbol = sdkToken.symbol,
|
||||
decimals = sdkToken.decimals,
|
||||
|
|
@ -84,8 +84,6 @@ internal class ResponseCurrenciesFactory(private val demoConfig: DemoConfig) {
|
|||
iconUrl = getTokenIconUrl(blockchain, sdkToken),
|
||||
contractAddress = sdkToken.contractAddress,
|
||||
isCustom = isCustomToken(id),
|
||||
blockchainName = blockchain.fullName,
|
||||
standardType = getTokenStandardType(blockchain, sdkToken),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ import com.tangem.blockchain.common.IconsUtil
|
|||
import com.tangem.domain.common.DerivationStyleProvider
|
||||
import com.tangem.domain.common.extensions.toCoinId
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency.ID
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.blockchain.common.Token as SdkToken
|
||||
|
|
@ -31,12 +30,6 @@ internal fun getBlockchain(networkId: Network.ID): Blockchain {
|
|||
return Blockchain.fromId(networkId.value)
|
||||
}
|
||||
|
||||
internal fun getNetworkId(blockchain: Blockchain): Network.ID {
|
||||
val value = blockchain.id
|
||||
|
||||
return Network.ID(value)
|
||||
}
|
||||
|
||||
internal fun getCoinId(blockchain: Blockchain): ID {
|
||||
return getTokenOrCoinId(blockchain, token = null)
|
||||
}
|
||||
|
|
@ -45,16 +38,6 @@ internal fun getTokenId(blockchain: Blockchain, token: SdkToken): ID {
|
|||
return getTokenOrCoinId(blockchain, token)
|
||||
}
|
||||
|
||||
internal fun getTokenStandardType(blockchain: Blockchain, token: SdkToken): CryptoCurrency.StandardType {
|
||||
return when (blockchain) {
|
||||
Blockchain.Ethereum, Blockchain.EthereumTestnet -> CryptoCurrency.StandardType.ERC20
|
||||
Blockchain.BSC, Blockchain.BSCTestnet -> CryptoCurrency.StandardType.BEP20
|
||||
Blockchain.Binance, Blockchain.BinanceTestnet -> CryptoCurrency.StandardType.BEP2
|
||||
Blockchain.Tron, Blockchain.TronTestnet -> CryptoCurrency.StandardType.TRC20
|
||||
else -> CryptoCurrency.StandardType.Unspecified(token.name)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getTokenIconUrl(blockchain: Blockchain, token: SdkToken): String? {
|
||||
val tokenId = token.id
|
||||
|
||||
|
|
@ -83,7 +66,7 @@ private fun getTokenOrCoinId(blockchain: Blockchain, token: SdkToken?): ID {
|
|||
else -> TOKEN_ID_PREFIX to CurrencyIdSuffix(rawId = sdkTokenId)
|
||||
}
|
||||
|
||||
return ID(prefix, getNetworkId(blockchain), suffix)
|
||||
return ID(prefix, Network.ID(blockchain.id), suffix)
|
||||
}
|
||||
|
||||
private fun getTokenIconUrlFromDefaultHost(tokenId: String): String {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ internal class UserTokensResponseFactory {
|
|||
}
|
||||
|
||||
private fun createResponseToken(currency: CryptoCurrency): UserTokensResponse.Token {
|
||||
val blockchain = getBlockchain(currency.networkId)
|
||||
val blockchain = getBlockchain(currency.network.id)
|
||||
|
||||
return UserTokensResponse.Token(
|
||||
id = currency.id.rawCurrencyId,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import java.io.Serializable
|
|||
* Represents a generic cryptocurrency.
|
||||
*
|
||||
* @property id Unique identifier for the cryptocurrency.
|
||||
* @property networkId Identifier for the network to which the cryptocurrency belongs.
|
||||
* @property network The network to which the cryptocurrency belongs.
|
||||
* @property name Human-readable name of the cryptocurrency.
|
||||
* @property symbol Symbol of the cryptocurrency.
|
||||
* @property decimals Number of decimal places used by the cryptocurrency.
|
||||
|
|
@ -14,11 +14,11 @@ import java.io.Serializable
|
|||
* @property derivationPath Optional path used for key derivation. `null` if the wallet does not support the
|
||||
* [HD Wallet](https://coinsutra.com/hd-wallets-deterministic-wallet/) feature.
|
||||
*/
|
||||
// TODO: [REDACTED_JIRA] delete serializable
|
||||
// FIXME: Remove serialization [REDACTED_JIRA]
|
||||
sealed class CryptoCurrency : Serializable {
|
||||
|
||||
abstract val id: ID
|
||||
abstract val networkId: Network.ID
|
||||
abstract val network: Network
|
||||
abstract val name: String
|
||||
abstract val symbol: String
|
||||
abstract val decimals: Int
|
||||
|
|
@ -30,7 +30,7 @@ sealed class CryptoCurrency : Serializable {
|
|||
*/
|
||||
data class Coin(
|
||||
override val id: ID,
|
||||
override val networkId: Network.ID,
|
||||
override val network: Network,
|
||||
override val name: String,
|
||||
override val symbol: String,
|
||||
override val decimals: Int,
|
||||
|
|
@ -51,7 +51,7 @@ sealed class CryptoCurrency : Serializable {
|
|||
*/
|
||||
data class Token(
|
||||
override val id: ID,
|
||||
override val networkId: Network.ID,
|
||||
override val network: Network,
|
||||
override val name: String,
|
||||
override val symbol: String,
|
||||
override val decimals: Int,
|
||||
|
|
@ -59,8 +59,6 @@ sealed class CryptoCurrency : Serializable {
|
|||
override val derivationPath: String?,
|
||||
val contractAddress: String,
|
||||
val isCustom: Boolean,
|
||||
val blockchainName: String, // TODO: Move this field to proper entity
|
||||
val standardType: StandardType, // TODO: Move this field to proper entity
|
||||
) : CryptoCurrency() {
|
||||
|
||||
init {
|
||||
|
|
@ -79,6 +77,7 @@ sealed class CryptoCurrency : Serializable {
|
|||
* @property rawCurrencyId Represents not unique currency ID from the blockchain network. `null` if
|
||||
* its ID of the custom token.
|
||||
*/
|
||||
// FIXME: Remove serialization [REDACTED_JIRA]
|
||||
data class ID(
|
||||
private val prefix: Prefix,
|
||||
private val networkId: Network.ID,
|
||||
|
|
@ -114,6 +113,7 @@ sealed class CryptoCurrency : Serializable {
|
|||
*
|
||||
* The suffix can either be a raw ID or a contract address.
|
||||
*/
|
||||
// FIXME: Remove serialization [REDACTED_JIRA]
|
||||
sealed class Suffix : Serializable {
|
||||
|
||||
/** The value of the suffix, which could be either a raw ID or a contract address. */
|
||||
|
|
@ -135,26 +135,6 @@ sealed class CryptoCurrency : Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
sealed class StandardType {
|
||||
abstract val name: String
|
||||
|
||||
object ERC20 : StandardType() {
|
||||
override val name: String = "ERC20"
|
||||
}
|
||||
object TRC20 : StandardType() {
|
||||
override val name: String = "TRC20"
|
||||
}
|
||||
object BEP20 : StandardType() {
|
||||
override val name: String = "BEP20"
|
||||
}
|
||||
object BEP2 : StandardType() {
|
||||
override val name: String = "BEP2"
|
||||
}
|
||||
class Unspecified(val tokenName: String) : StandardType() {
|
||||
override val name: String = tokenName
|
||||
}
|
||||
}
|
||||
|
||||
protected fun checkProperties() {
|
||||
require(name.isNotBlank()) { "Crypto currency name must not be blank" }
|
||||
require(symbol.isNotBlank()) { "Crypto currency symbol must not be blank" }
|
||||
|
|
|
|||
|
|
@ -1,29 +1,80 @@
|
|||
package com.tangem.domain.tokens.models
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Represents a blockchain network, identified by a unique ID and a human-readable name.
|
||||
* Represents a blockchain network, identified by a unique ID, a human-readable name, and its standard type.
|
||||
*
|
||||
* @property id The unique identifier of the network, encapsulated as an inline value class.
|
||||
* This class encapsulates the primary details of a blockchain network, such as its ID, name,
|
||||
* whether it operates as a test network, and the type of blockchain standard it conforms to
|
||||
* (e.g., ERC20, BEP20).
|
||||
*
|
||||
* @property id The unique identifier of the network.
|
||||
* @property name The human-readable name of the network, such as "Ethereum" or "Bitcoin".
|
||||
*
|
||||
* @throws IllegalArgumentException If the name or ID is blank.
|
||||
* @property isTestnet Indicates whether the network is a test network or a main network.
|
||||
* @property standardType The type of blockchain standard the network adheres to.
|
||||
*/
|
||||
data class Network(val id: ID, val name: String) {
|
||||
// FIXME: Remove serialization [REDACTED_JIRA]
|
||||
data class Network(
|
||||
val id: ID,
|
||||
val name: String,
|
||||
val isTestnet: Boolean,
|
||||
val standardType: StandardType,
|
||||
) : Serializable {
|
||||
|
||||
init {
|
||||
require(name.isNotBlank()) { "Network name must not be blank" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a unique identifier for a network.
|
||||
* Represents a unique identifier for a blockchain network.
|
||||
*
|
||||
* @property value The string value of the network ID.
|
||||
* @property value The string representation of the network ID.
|
||||
*/
|
||||
// FIXME: Remove serialization [REDACTED_JIRA]
|
||||
@JvmInline
|
||||
value class ID(val value: String) {
|
||||
value class ID(val value: String) : Serializable {
|
||||
|
||||
init {
|
||||
require(value.isNotBlank()) { "Network ID must not be blank" }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the type of blockchain standard that a network adheres to.
|
||||
*
|
||||
* Blockchain networks often follow certain standards that dictate how tokens operate on them.
|
||||
* These standards can define functionalities such as how transactions are processed,
|
||||
* how tokens are minted or burned, and more.
|
||||
*
|
||||
* @property name The human-readable name of the standard type.
|
||||
*/
|
||||
sealed class StandardType {
|
||||
abstract val name: String
|
||||
|
||||
/** Represents the ERC20 token standard, common on the Ethereum network. */
|
||||
object ERC20 : StandardType() {
|
||||
override val name: String = "ERC20"
|
||||
}
|
||||
|
||||
/** Represents the TRC20 token standard, common on the TRON network. */
|
||||
object TRC20 : StandardType() {
|
||||
override val name: String = "TRC20"
|
||||
}
|
||||
|
||||
/** Represents the BEP20 token standard, common on the Binance Smart Chain network. */
|
||||
object BEP20 : StandardType() {
|
||||
override val name: String = "BEP20"
|
||||
}
|
||||
|
||||
/** Represents the BEP2 token standard, common on the Binance Chain network. */
|
||||
object BEP2 : StandardType() {
|
||||
override val name: String = "BEP2"
|
||||
}
|
||||
|
||||
/** Represents a network that does not adhere to a predefined standard type. */
|
||||
class Unspecified(val networkName: String) : StandardType() {
|
||||
override val name: String = networkName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.raise.*
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.either
|
||||
import arrow.core.raise.ensure
|
||||
import arrow.core.raise.withError
|
||||
import com.tangem.domain.tokens.error.TokenListSortingError
|
||||
import com.tangem.domain.tokens.error.mapper.mapToTokenListSortingError
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.operations.TokenListSortingOperations
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class ToggleTokenListGroupingUseCase(
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
|
|
@ -34,14 +34,10 @@ class ToggleTokenListGroupingUseCase(
|
|||
|
||||
private fun Raise<TokenListSortingError>.groupTokens(tokenList: TokenList.Ungrouped): TokenList.GroupedByNetwork {
|
||||
val sortingOperations = TokenListSortingOperations(tokenList)
|
||||
val tokens = withError(TokenListSortingOperations.Error::mapToTokenListSortingError) {
|
||||
sortingOperations.getTokens().bind()
|
||||
}
|
||||
|
||||
val networks = getNetworks(tokens.map { it.currency.networkId }.toSet())
|
||||
return TokenList.GroupedByNetwork(
|
||||
groups = withError(TokenListSortingOperations.Error::mapToTokenListSortingError) {
|
||||
sortingOperations.getGroupedTokens(networks).bind()
|
||||
sortingOperations.getGroupedTokens().bind()
|
||||
},
|
||||
totalFiatBalance = tokenList.totalFiatBalance,
|
||||
sortedBy = sortingOperations.getSortType(),
|
||||
|
|
@ -61,11 +57,4 @@ class ToggleTokenListGroupingUseCase(
|
|||
sortedBy = sortingOperations.getSortType(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun Raise<TokenListSortingError>.getNetworks(networksIds: Set<Network.ID>): Set<Network> {
|
||||
return catch(
|
||||
block = { networksRepository.getNetworks(networksIds) },
|
||||
catch = { raise(TokenListSortingError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -36,11 +36,10 @@ class ToggleTokenListSortingUseCase(
|
|||
tokenList: TokenList.GroupedByNetwork,
|
||||
): TokenList.GroupedByNetwork {
|
||||
val operations = getSortingOperations(tokenList)
|
||||
val networks = tokenList.groups.map { it.network }.toSet()
|
||||
|
||||
return tokenList.copy(
|
||||
groups = withError(TokenListSortingOperations.Error::mapToTokenListSortingError) {
|
||||
operations.getGroupedTokens(networks).bind()
|
||||
operations.getGroupedTokens().bind()
|
||||
},
|
||||
sortedBy = operations.getSortType(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,5 @@ internal fun TokenListOperations.Error.mapToTokenListError(): TokenListError {
|
|||
is TokenListOperations.Error.DataError -> TokenListError.DataError(this.cause)
|
||||
is TokenListOperations.Error.UnableToSortTokenList ->
|
||||
TokenListError.UnableToSortTokenList(this.unsortedTokenList)
|
||||
is TokenListOperations.Error.UnableToGroupTokenList ->
|
||||
TokenListError.UnableToSortTokenList(this.ungroupedTokenList)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,6 @@ import com.tangem.domain.tokens.operations.TokenListSortingOperations
|
|||
internal fun TokenListSortingOperations.Error.mapToTokenListSortingError(): TokenListSortingError {
|
||||
return when (this) {
|
||||
is TokenListSortingOperations.Error.EmptyTokens -> TokenListSortingError.TokenListIsEmpty
|
||||
is TokenListSortingOperations.Error.EmptyNetworks,
|
||||
is TokenListSortingOperations.Error.NetworkNotFound,
|
||||
-> TokenListSortingError.UnableToSortTokenList
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ internal class CurrenciesStatusesOperations(
|
|||
val statusFlow = getNetworksStatuses(networksIds)
|
||||
.map { maybeStatuses ->
|
||||
maybeStatuses.map { statuses ->
|
||||
statuses.singleOrNull { it.networkId == currency.networkId }
|
||||
statuses.singleOrNull { it.networkId == currency.network.id }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ internal class CurrenciesStatusesOperations(
|
|||
|
||||
currencies.map { currency ->
|
||||
val quote = quotes?.firstOrNull { it.rawCurrencyId == currency.id.rawCurrencyId }
|
||||
val networkStatus = networksStatuses?.firstOrNull { it.networkId == currency.networkId }
|
||||
val networkStatus = networksStatuses?.firstOrNull { it.networkId == currency.network.id }
|
||||
|
||||
createStatus(currency, quote, networkStatus, ignoreQuote = quotesRetrievingFailed)
|
||||
}
|
||||
|
|
@ -205,7 +205,7 @@ internal class CurrenciesStatusesOperations(
|
|||
currencies: NonEmptyList<CryptoCurrency>,
|
||||
): Pair<NonEmptySet<Network.ID>, NonEmptySet<CryptoCurrency.ID>> {
|
||||
val currencyIdToNetworkId = currencies.associate { currency ->
|
||||
currency.id to currency.networkId
|
||||
currency.id to currency.network.id
|
||||
}
|
||||
val currenciesIds = currencyIdToNetworkId.keys.toNonEmptySetOrNull()
|
||||
val networksIds = currencyIdToNetworkId.values.toNonEmptySetOrNull()
|
||||
|
|
|
|||
|
|
@ -5,16 +5,13 @@ import arrow.core.raise.*
|
|||
import com.tangem.domain.tokens.GetTokenListUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class TokenListOperations(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val userWalletId: UserWalletId,
|
||||
private val tokens: List<CryptoCurrencyStatus>,
|
||||
) {
|
||||
|
|
@ -25,7 +22,6 @@ internal class TokenListOperations(
|
|||
useCase: GetTokenListUseCase,
|
||||
) : this(
|
||||
currenciesRepository = useCase.currenciesRepository,
|
||||
networksRepository = useCase.networksRepository,
|
||||
userWalletId = userWalletId,
|
||||
tokens = tokens,
|
||||
)
|
||||
|
|
@ -70,37 +66,21 @@ internal class TokenListOperations(
|
|||
sortByBalance = isSortedByBalance,
|
||||
)
|
||||
|
||||
return createTokenList(currencies, sortingOperations, fiatBalance, isGrouped)
|
||||
return createTokenList(sortingOperations, fiatBalance, isGrouped)
|
||||
}
|
||||
|
||||
private fun Raise<Error>.createTokenList(
|
||||
tokens: NonEmptyList<CryptoCurrencyStatus>,
|
||||
sortingOperations: TokenListSortingOperations,
|
||||
fiatBalance: TokenList.FiatBalance,
|
||||
isGrouped: Boolean,
|
||||
): TokenList {
|
||||
return if (isGrouped) {
|
||||
val networks = ensureNotNull(getNetworks(tokens).toNonEmptySetOrNull()) {
|
||||
Error.UnableToGroupTokenList(
|
||||
ungroupedTokenList = createUngroupedTokenList(sortingOperations, fiatBalance),
|
||||
)
|
||||
}
|
||||
|
||||
createGroupedTokenList(sortingOperations, fiatBalance, networks)
|
||||
createGroupedTokenList(sortingOperations, fiatBalance)
|
||||
} else {
|
||||
createUngroupedTokenList(sortingOperations, fiatBalance)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Raise<Error>.getNetworks(tokensNes: NonEmptyList<CryptoCurrencyStatus>): Set<Network> {
|
||||
val networksIds = tokensNes.map { it.currency.networkId }.toNonEmptySet()
|
||||
|
||||
return catch(
|
||||
block = { networksRepository.getNetworks(networksIds) },
|
||||
catch = { raise(Error.DataError(it)) },
|
||||
)
|
||||
}
|
||||
|
||||
private fun Raise<Error>.createUngroupedTokenList(
|
||||
sortingOperations: TokenListSortingOperations,
|
||||
fiatBalance: TokenList.FiatBalance,
|
||||
|
|
@ -118,7 +98,6 @@ internal class TokenListOperations(
|
|||
private fun Raise<Error>.createGroupedTokenList(
|
||||
sortingOperations: TokenListSortingOperations,
|
||||
fiatBalance: TokenList.FiatBalance,
|
||||
networks: NonEmptySet<Network>,
|
||||
): TokenList.GroupedByNetwork = TokenList.GroupedByNetwork(
|
||||
sortedBy = sortingOperations.getSortType(),
|
||||
totalFiatBalance = fiatBalance,
|
||||
|
|
@ -126,7 +105,7 @@ internal class TokenListOperations(
|
|||
transform = { e ->
|
||||
Error.fromTokenListOperations(e) { createUnsortedUngroupedTokenList(tokens, fiatBalance) }
|
||||
},
|
||||
block = { sortingOperations.getGroupedTokens(networks).bind() },
|
||||
block = { sortingOperations.getGroupedTokens().bind() },
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -159,8 +138,6 @@ internal class TokenListOperations(
|
|||
|
||||
data class UnableToSortTokenList(val unsortedTokenList: TokenList.Ungrouped) : Error()
|
||||
|
||||
data class UnableToGroupTokenList(val ungroupedTokenList: TokenList.Ungrouped) : Error()
|
||||
|
||||
data class DataError(val cause: Throwable) : Error()
|
||||
|
||||
internal companion object {
|
||||
|
|
@ -169,7 +146,6 @@ internal class TokenListOperations(
|
|||
e: TokenListSortingOperations.Error,
|
||||
createUnsortedUngroupedTokenList: () -> TokenList.Ungrouped,
|
||||
): Error = when (e) {
|
||||
is TokenListSortingOperations.Error.EmptyNetworks,
|
||||
is TokenListSortingOperations.Error.EmptyTokens,
|
||||
is TokenListSortingOperations.Error.NetworkNotFound,
|
||||
-> UnableToSortTokenList(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package com.tangem.domain.tokens.operations
|
||||
|
||||
import arrow.core.*
|
||||
import arrow.core.Either
|
||||
import arrow.core.NonEmptyList
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.either
|
||||
import arrow.core.raise.ensure
|
||||
import arrow.core.raise.ensureNotNull
|
||||
import arrow.core.toNonEmptyListOrNull
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.NetworkGroup
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
|
|
@ -31,16 +33,13 @@ internal class TokenListSortingOperations(
|
|||
sortByBalance = sortByBalance,
|
||||
)
|
||||
|
||||
fun getGroupedTokens(networks: Set<Network>): Either<Error, NonEmptyList<NetworkGroup>> = either {
|
||||
fun getGroupedTokens(): Either<Error, NonEmptyList<NetworkGroup>> = either {
|
||||
ensure(currencies.isNotEmpty()) { Error.EmptyTokens }
|
||||
val networksNes = ensureNotNull(networks.toNonEmptySetOrNull()) {
|
||||
Error.EmptyNetworks
|
||||
}
|
||||
|
||||
if (sortByBalance) {
|
||||
groupAndSortTokensByBalance(networksNes)
|
||||
groupAndSortTokensByBalance()
|
||||
} else {
|
||||
groupTokens(networksNes)
|
||||
groupTokens()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -54,14 +53,10 @@ internal class TokenListSortingOperations(
|
|||
|
||||
fun getSortType(): TokenList.SortType = if (sortByBalance) TokenList.SortType.BALANCE else TokenList.SortType.NONE
|
||||
|
||||
private fun Raise<Error>.groupTokens(networks: NonEmptySet<Network>): NonEmptyList<NetworkGroup> {
|
||||
private fun Raise<Error>.groupTokens(): NonEmptyList<NetworkGroup> {
|
||||
val groupedTokens = currencies
|
||||
.groupBy { it.currency.networkId }
|
||||
.map { (networkId, tokens) ->
|
||||
val network = ensureNotNull(networks.firstOrNull { it.id == networkId }) {
|
||||
Error.NetworkNotFound(networkId)
|
||||
}
|
||||
|
||||
.groupBy { it.currency.network }
|
||||
.map { (network, tokens) ->
|
||||
NetworkGroup(
|
||||
network = network,
|
||||
currencies = ensureNotNull(tokens.toNonEmptyListOrNull()) { Error.EmptyTokens },
|
||||
|
|
@ -72,8 +67,8 @@ internal class TokenListSortingOperations(
|
|||
return ensureNotNull(groupedTokens) { Error.EmptyTokens }
|
||||
}
|
||||
|
||||
private fun Raise<Error>.groupAndSortTokensByBalance(networks: NonEmptySet<Network>): NonEmptyList<NetworkGroup> {
|
||||
val groupsWithSortedTokens = groupTokens(networks)
|
||||
private fun Raise<Error>.groupAndSortTokensByBalance(): NonEmptyList<NetworkGroup> {
|
||||
val groupsWithSortedTokens = groupTokens()
|
||||
.map { group ->
|
||||
val tokens = group.currencies as? NonEmptyList<CryptoCurrencyStatus>
|
||||
?: error("Tokens can not be empty here")
|
||||
|
|
@ -110,8 +105,6 @@ internal class TokenListSortingOperations(
|
|||
|
||||
object EmptyTokens : Error()
|
||||
|
||||
object EmptyNetworks : Error()
|
||||
|
||||
data class NetworkNotFound(val networkId: Network.ID) : Error()
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,6 @@ import com.tangem.domain.tokens.mock.MockTokens
|
|||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.models.Quote
|
||||
import com.tangem.domain.tokens.repository.MockCurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.MockNetworksRepository
|
||||
|
|
@ -109,23 +108,6 @@ internal class GetTokenListUseCaseTest {
|
|||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when networks getting failed and list is groped then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokenListError.DataError(DataError.NetworkError.NoInternetConnection).left()
|
||||
|
||||
val useCase = getUseCase(
|
||||
networks = DataError.NetworkError.NoInternetConnection.left(),
|
||||
isGrouped = flowOf(true.right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when networks statuses getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
|
|
@ -212,22 +194,6 @@ internal class GetTokenListUseCaseTest {
|
|||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when list is grouped and networks getting failed then error should be received`() = runTest {
|
||||
val expectedResult = TokenListError.DataError(DataError.NetworkError.NoInternetConnection).left()
|
||||
|
||||
val useCase = getUseCase(
|
||||
networks = DataError.NetworkError.NoInternetConnection.left(),
|
||||
isGrouped = flowOf(true.right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when list is sorted and ungrouped then correct token list should be received`() = runTest {
|
||||
val expectedResult = listOf(
|
||||
|
|
@ -285,27 +251,6 @@ internal class GetTokenListUseCaseTest {
|
|||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when networks is empty and list is grouped then ungrouped list should be received`() = runTest {
|
||||
val expectedResult = listOf(
|
||||
TokenListError.UnableToSortTokenList(MockTokenLists.loadingUngroupedTokenList).left(),
|
||||
TokenListError.UnableToSortTokenList(MockTokenLists.failedUngroupedTokenList).left(),
|
||||
)
|
||||
|
||||
val useCase = getUseCase(
|
||||
networks = emptySet<Network>().right(),
|
||||
isGrouped = flowOf(true.right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId)
|
||||
.take(count = 2)
|
||||
.toList()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when tokens flow is empty then error should be received`() = runTest {
|
||||
val expectedResult = TokenListError.EmptyTokens.left()
|
||||
|
|
@ -390,7 +335,6 @@ internal class GetTokenListUseCaseTest {
|
|||
private fun getUseCase(
|
||||
tokens: Flow<Either<DataError, List<CryptoCurrency>>> = flowOf(MockTokens.tokens.right()),
|
||||
quotes: Flow<Either<DataError, Set<Quote>>> = flowOf(MockQuotes.quotes.right()),
|
||||
networks: Either<DataError, Set<Network>> = MockNetworks.networks.right(),
|
||||
statuses: Flow<Either<DataError, Set<NetworkStatus>>> = flowOf(MockNetworks.errorNetworksStatuses.right()),
|
||||
isGrouped: Flow<Either<DataError, Boolean>> = flowOf(MockTokenLists.isGrouped.right()),
|
||||
isSortedByBalance: Flow<Either<DataError, Boolean>> = flowOf(MockTokenLists.isSortedByBalance.right()),
|
||||
|
|
@ -404,6 +348,6 @@ internal class GetTokenListUseCaseTest {
|
|||
isSortedByBalance = isSortedByBalance,
|
||||
),
|
||||
quotesRepository = MockQuotesRepository(quotes),
|
||||
networksRepository = MockNetworksRepository(networks, statuses),
|
||||
networksRepository = MockNetworksRepository(MockNetworks.networks.right(), statuses),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,17 +1,11 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.core.error.DataError
|
||||
import com.tangem.domain.tokens.error.TokenListSortingError
|
||||
import com.tangem.domain.tokens.mock.MockNetworks
|
||||
import com.tangem.domain.tokens.mock.MockTokenLists
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.repository.MockNetworksRepository
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
|
|
@ -143,38 +137,7 @@ internal class ToggleTokenListGroupingTest {
|
|||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when list is ungrouped but networks is empty then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokenListSortingError.UnableToSortTokenList.left()
|
||||
|
||||
val useCase = getUseCase(networks = emptySet<Network>().right())
|
||||
|
||||
// When
|
||||
val result = useCase(MockTokenLists.unsortedUngroupedTokenList)
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when list is ungrouped but networks getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val error = DataError.NetworkError.NoInternetConnection
|
||||
val expectedResult = TokenListSortingError.DataError(error).left()
|
||||
|
||||
val useCase = getUseCase(networks = error.left())
|
||||
|
||||
// When
|
||||
val result = useCase(MockTokenLists.unsortedUngroupedTokenList)
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
private fun getUseCase(networks: Either<DataError, Set<Network>> = MockNetworks.networks.right()) =
|
||||
ToggleTokenListGroupingUseCase(
|
||||
networksRepository = MockNetworksRepository(networks, statuses = flowOf()),
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
private fun getUseCase() = ToggleTokenListGroupingUseCase(
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
}
|
||||
|
|
@ -14,16 +14,22 @@ internal object MockNetworks {
|
|||
val network1 = Network(
|
||||
id = Network.ID("network1"),
|
||||
name = "Network One",
|
||||
isTestnet = false,
|
||||
standardType = Network.StandardType.ERC20,
|
||||
)
|
||||
|
||||
val network2 = Network(
|
||||
id = Network.ID("network2"),
|
||||
name = "Network Two",
|
||||
isTestnet = false,
|
||||
standardType = Network.StandardType.ERC20,
|
||||
)
|
||||
|
||||
val network3 = Network(
|
||||
id = Network.ID("network3"),
|
||||
name = "Network Three",
|
||||
isTestnet = false,
|
||||
standardType = Network.StandardType.ERC20,
|
||||
)
|
||||
|
||||
val networks = nonEmptySetOf(network1, network2, network3)
|
||||
|
|
|
|||
|
|
@ -10,21 +10,21 @@ internal object MockNetworksGroups {
|
|||
val networkGroup1 = NetworkGroup(
|
||||
network = MockNetworks.network1,
|
||||
currencies = MockTokensStates.failedTokenStates
|
||||
.filter { it.currency.networkId == MockNetworks.network1.id }
|
||||
.filter { it.currency.network.id == MockNetworks.network1.id }
|
||||
.toNonEmptyListOrNull()!!,
|
||||
)
|
||||
|
||||
val networkGroup2 = NetworkGroup(
|
||||
network = MockNetworks.network2,
|
||||
currencies = MockTokensStates.failedTokenStates
|
||||
.filter { it.currency.networkId == MockNetworks.network2.id }
|
||||
.filter { it.currency.network.id == MockNetworks.network2.id }
|
||||
.toNonEmptyListOrNull()!!,
|
||||
)
|
||||
|
||||
val networkGroup3 = NetworkGroup(
|
||||
network = MockNetworks.network3,
|
||||
currencies = MockTokensStates.failedTokenStates
|
||||
.filter { it.currency.networkId == MockNetworks.network3.id }
|
||||
.filter { it.currency.network.id == MockNetworks.network3.id }
|
||||
.toNonEmptyListOrNull()!!,
|
||||
)
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ internal object MockNetworksGroups {
|
|||
val loadedNetworksGroups = failedNetworksGroups.map { group ->
|
||||
group.copy(
|
||||
currencies = MockTokensStates.loadedTokensStates
|
||||
.filter { it.currency.networkId == group.network.id }
|
||||
.filter { it.currency.network.id == group.network.id }
|
||||
.toNonEmptyListOrNull()!!,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ internal object MockTokens {
|
|||
val token1
|
||||
get() = CryptoCurrency.Coin(
|
||||
id = ID(ID.Prefix.COIN_PREFIX, MockNetworks.network1.id, ID.Suffix.RawID("token1")),
|
||||
networkId = MockNetworks.network1.id,
|
||||
network = MockNetworks.network1,
|
||||
name = "Token 1",
|
||||
symbol = "T1",
|
||||
decimals = 8,
|
||||
|
|
@ -18,7 +18,7 @@ internal object MockTokens {
|
|||
val token2
|
||||
get() = CryptoCurrency.Token(
|
||||
id = ID(ID.Prefix.TOKEN_PREFIX, MockNetworks.network1.id, ID.Suffix.RawID("token2")),
|
||||
networkId = MockNetworks.network1.id,
|
||||
network = MockNetworks.network1,
|
||||
name = "Token 2",
|
||||
symbol = "T2",
|
||||
isCustom = false,
|
||||
|
|
@ -26,13 +26,11 @@ internal object MockTokens {
|
|||
iconUrl = null,
|
||||
contractAddress = "address",
|
||||
derivationPath = null,
|
||||
blockchainName = "Ethereum",
|
||||
standardType = CryptoCurrency.StandardType.ERC20,
|
||||
)
|
||||
val token3
|
||||
get() = CryptoCurrency.Token(
|
||||
id = ID(ID.Prefix.TOKEN_PREFIX, MockNetworks.network1.id, ID.Suffix.RawID("token3")),
|
||||
networkId = MockNetworks.network1.id,
|
||||
network = MockNetworks.network1,
|
||||
name = "Token 3",
|
||||
symbol = "T3",
|
||||
isCustom = false,
|
||||
|
|
@ -40,13 +38,11 @@ internal object MockTokens {
|
|||
iconUrl = null,
|
||||
contractAddress = "address",
|
||||
derivationPath = null,
|
||||
blockchainName = "Ethereum",
|
||||
standardType = CryptoCurrency.StandardType.ERC20,
|
||||
)
|
||||
val token4
|
||||
get() = CryptoCurrency.Coin(
|
||||
id = ID(ID.Prefix.COIN_PREFIX, MockNetworks.network2.id, ID.Suffix.RawID("token4")),
|
||||
networkId = MockNetworks.network2.id,
|
||||
network = MockNetworks.network2,
|
||||
name = "Token 4",
|
||||
symbol = "T4",
|
||||
decimals = 8,
|
||||
|
|
@ -56,7 +52,7 @@ internal object MockTokens {
|
|||
val token5
|
||||
get() = CryptoCurrency.Token(
|
||||
id = ID(ID.Prefix.TOKEN_PREFIX, MockNetworks.network2.id, ID.Suffix.RawID("token5")),
|
||||
networkId = MockNetworks.network2.id,
|
||||
network = MockNetworks.network2,
|
||||
name = "Token 5",
|
||||
symbol = "T5",
|
||||
isCustom = false,
|
||||
|
|
@ -64,13 +60,11 @@ internal object MockTokens {
|
|||
iconUrl = null,
|
||||
contractAddress = "address",
|
||||
derivationPath = null,
|
||||
blockchainName = "Ethereum",
|
||||
standardType = CryptoCurrency.StandardType.ERC20,
|
||||
)
|
||||
val token6
|
||||
get() = CryptoCurrency.Token(
|
||||
id = ID(ID.Prefix.TOKEN_PREFIX, MockNetworks.network2.id, ID.Suffix.RawID("token6")),
|
||||
networkId = MockNetworks.network2.id,
|
||||
network = MockNetworks.network2,
|
||||
name = "Token 6",
|
||||
symbol = "T6",
|
||||
isCustom = false,
|
||||
|
|
@ -78,13 +72,11 @@ internal object MockTokens {
|
|||
iconUrl = null,
|
||||
contractAddress = "address",
|
||||
derivationPath = null,
|
||||
blockchainName = "Ethereum",
|
||||
standardType = CryptoCurrency.StandardType.ERC20,
|
||||
)
|
||||
val token7
|
||||
get() = CryptoCurrency.Coin(
|
||||
id = ID(ID.Prefix.COIN_PREFIX, MockNetworks.network3.id, ID.Suffix.RawID("token7")),
|
||||
networkId = MockNetworks.network3.id,
|
||||
network = MockNetworks.network3,
|
||||
name = "Token 7",
|
||||
symbol = "T7",
|
||||
decimals = 8,
|
||||
|
|
@ -94,7 +86,7 @@ internal object MockTokens {
|
|||
val token8
|
||||
get() = CryptoCurrency.Token(
|
||||
id = ID(ID.Prefix.TOKEN_PREFIX, MockNetworks.network3.id, ID.Suffix.RawID("token8")),
|
||||
networkId = MockNetworks.network3.id,
|
||||
network = MockNetworks.network3,
|
||||
name = "Token 8",
|
||||
symbol = "T8",
|
||||
isCustom = false,
|
||||
|
|
@ -102,13 +94,11 @@ internal object MockTokens {
|
|||
iconUrl = null,
|
||||
contractAddress = "address",
|
||||
derivationPath = null,
|
||||
blockchainName = "Ethereum",
|
||||
standardType = CryptoCurrency.StandardType.ERC20,
|
||||
)
|
||||
val token9
|
||||
get() = CryptoCurrency.Token(
|
||||
id = ID(ID.Prefix.TOKEN_PREFIX, MockNetworks.network3.id, ID.Suffix.RawID("token9")),
|
||||
networkId = MockNetworks.network3.id,
|
||||
network = MockNetworks.network3,
|
||||
name = "Token 9",
|
||||
symbol = "T9",
|
||||
isCustom = false,
|
||||
|
|
@ -116,13 +106,11 @@ internal object MockTokens {
|
|||
iconUrl = null,
|
||||
contractAddress = "address",
|
||||
derivationPath = null,
|
||||
blockchainName = "Ethereum",
|
||||
standardType = CryptoCurrency.StandardType.ERC20,
|
||||
)
|
||||
val token10
|
||||
get() = CryptoCurrency.Token(
|
||||
id = ID(ID.Prefix.TOKEN_PREFIX, MockNetworks.network3.id, ID.Suffix.RawID("token10")),
|
||||
networkId = MockNetworks.network3.id,
|
||||
network = MockNetworks.network3,
|
||||
name = "Token 10",
|
||||
symbol = "T10",
|
||||
isCustom = false,
|
||||
|
|
@ -130,8 +118,6 @@ internal object MockTokens {
|
|||
iconUrl = null,
|
||||
contractAddress = "address",
|
||||
derivationPath = null,
|
||||
blockchainName = "Ethereum",
|
||||
standardType = CryptoCurrency.StandardType.ERC20,
|
||||
)
|
||||
|
||||
val tokens = listOf(token1, token2, token3, token4, token5, token6, token7, token8, token9, token10)
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ internal object MockTokensStates {
|
|||
|
||||
val loadedTokensStates = failedTokenStates.map { status ->
|
||||
val networkStatus = MockNetworks.verifiedNetworksStatuses
|
||||
.first { it.networkId == status.currency.networkId }
|
||||
.first { it.networkId == status.currency.network.id }
|
||||
val amount = (networkStatus.value as NetworkStatus.Verified).amounts[status.currency.id]!!
|
||||
val quote = MockQuotes.quotes.first { it.rawCurrencyId == status.currency.id.rawCurrencyId }
|
||||
val fiatAmount = amount * quote.fiatRate
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ internal class TokenDetailsSkeletonStateConverter(
|
|||
currency = when (value.cryptoCurrency) {
|
||||
is CryptoCurrency.Coin -> TokenInfoBlockState.Currency.Native
|
||||
is CryptoCurrency.Token -> TokenInfoBlockState.Currency.Token(
|
||||
networkName = value.cryptoCurrency.standardType.name,
|
||||
blockchainName = value.cryptoCurrency.blockchainName,
|
||||
networkName = value.cryptoCurrency.network.standardType.name,
|
||||
blockchainName = value.cryptoCurrency.network.name,
|
||||
// TODO: [REDACTED_JIRA]
|
||||
networkIcon = R.drawable.img_eth_22,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ internal class CryptoCurrencyToDraggableItemConverter(
|
|||
): DraggableItem.Token {
|
||||
return DraggableItem.Token(
|
||||
tokenItemState = createTokenItemState(currencyStatus, appCurrency),
|
||||
groupId = getGroupHeaderId(currencyStatus.currency.networkId),
|
||||
groupId = getGroupHeaderId(currencyStatus.currency.network.id),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue