Updated on 2026-08-14
This commit is contained in:
parent
5463c87ff0
commit
37a31042c0
10 changed files with 1442 additions and 97 deletions
|
|
@ -0,0 +1,70 @@
|
|||
package com.tangem.domain.account.status.utils
|
||||
|
||||
import arrow.core.Option
|
||||
import arrow.core.raise.option
|
||||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
|
||||
/**
|
||||
* Extension functions for retrieving [AccountCryptoCurrency] from an [AccountList].
|
||||
*
|
||||
* This object provides convenient extension functions to search and retrieve [AccountCryptoCurrency] instances
|
||||
* from an [AccountList] using various parameters such as cryptocurrency ID and network.
|
||||
*
|
||||
* Usage example:
|
||||
* ```
|
||||
* val accountList: AccountList? = ...
|
||||
* val result: Option<AccountCryptoCurrency> = accountList.getAccountCryptoCurrency(currency)
|
||||
* result.fold(
|
||||
* ifEmpty = { /* handle not found */ },
|
||||
* ifSome = { accountCryptoCurrency -> /* use the found result */ }
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* @see AccountCryptoCurrency
|
||||
* @see AccountList
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
object AccountCryptoCurrencyOperations {
|
||||
|
||||
// region AccountList
|
||||
|
||||
/**
|
||||
* Retrieves the [AccountCryptoCurrency] for the specified [currency] from this [AccountList].
|
||||
*
|
||||
* @receiver the [AccountList] to search within, can be null
|
||||
* @param currency the cryptocurrency whose account association is to be retrieved
|
||||
* @return [Option] containing the [AccountCryptoCurrency] if found, or [Option.None] otherwise
|
||||
*/
|
||||
fun AccountList?.getAccountCryptoCurrency(currency: CryptoCurrency): Option<AccountCryptoCurrency> {
|
||||
return getAccountCryptoCurrency(currencyId = currency.id, network = currency.network)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the [AccountCryptoCurrency] for the specified [currencyId] and [network] from this [AccountList].
|
||||
*
|
||||
* @receiver the [AccountList] to search within, can be null
|
||||
* @param currencyId the ID of the cryptocurrency whose account association is to be retrieved
|
||||
* @param network the network associated with the cryptocurrency, can be null
|
||||
* @return [Option] containing the [AccountCryptoCurrency] if found, or [Option.None] otherwise
|
||||
*/
|
||||
fun AccountList?.getAccountCryptoCurrency(
|
||||
currencyId: CryptoCurrency.ID,
|
||||
network: Network?,
|
||||
): Option<AccountCryptoCurrency> = option {
|
||||
val accountList = this@getAccountCryptoCurrency
|
||||
|
||||
ensureNotNull(accountList)
|
||||
|
||||
val accountCryptoCurrency = AccountCryptoCurrencyStatusFinder(
|
||||
accountList = accountList,
|
||||
currencyId = currencyId,
|
||||
network = network,
|
||||
)
|
||||
|
||||
ensureNotNull(accountCryptoCurrency)
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.domain.account.status.utils
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrency
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatus
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatuses
|
||||
import com.tangem.domain.models.account.Account
|
||||
|
|
@ -9,16 +11,23 @@ import com.tangem.domain.models.account.AccountStatus
|
|||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.account.filterCryptoPortfolio
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.lib.crypto.derivation.AccountNodeRecognizer
|
||||
|
||||
/**
|
||||
* Finds the status of a specific cryptocurrency associated with an account from the provided account status list.
|
||||
* Finds a specific cryptocurrency or its status associated with an account from the provided account list.
|
||||
*
|
||||
* The base implementation uses [AccountList] for searching. For [AccountStatusList], it first converts
|
||||
* to [AccountList], finds the [AccountCryptoCurrency], then retrieves the status using accountId and currencyId.
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Suppress("MethodOverloading")
|
||||
internal object AccountCryptoCurrencyStatusFinder {
|
||||
|
||||
// region AccountCryptoCurrencyStatus methods
|
||||
|
||||
/**
|
||||
* Retrieves the [AccountCryptoCurrencyStatus] for the specified [currency] from the given [accountStatusList].
|
||||
*
|
||||
|
|
@ -48,25 +57,19 @@ internal object AccountCryptoCurrencyStatusFinder {
|
|||
currencyId: CryptoCurrency.ID,
|
||||
network: Network?,
|
||||
): AccountCryptoCurrencyStatus? {
|
||||
return accountStatusList.getExpectedAccountStatuses(network)
|
||||
.asSequence()
|
||||
.filterCryptoPortfolio()
|
||||
.mapNotNull { accountStatus ->
|
||||
val status = accountStatus.flattenCurrencies().firstOrNull { it.currency.id == currencyId }
|
||||
?: return@mapNotNull null
|
||||
val accountList = accountStatusList.toAccountList().getOrNull() ?: return null
|
||||
val accountCurrency = invoke(accountList, currencyId, network) ?: return null
|
||||
|
||||
AccountCryptoCurrencyStatus(account = accountStatus.account, status = status)
|
||||
}
|
||||
.firstOrNull()
|
||||
return accountStatusList.findStatus(accountCurrency)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a map of accounts to their corresponding list of [AccountCryptoCurrencyStatus] for the specified
|
||||
* Retrieves a map of accounts to their corresponding list of [CryptoCurrencyStatus] for the specified
|
||||
* list of [currencies] from the given [accountStatusList].
|
||||
*
|
||||
* @param accountStatusList the list of account statuses to search within.
|
||||
* @param currencies the list of cryptocurrencies whose statuses are to be retrieved.
|
||||
* @return a map where the key is the account and the value is a list of [AccountCryptoCurrencyStatus].
|
||||
* @return a map where the key is the account and the value is a list of [CryptoCurrencyStatus].
|
||||
*/
|
||||
operator fun invoke(
|
||||
accountStatusList: AccountStatusList,
|
||||
|
|
@ -104,15 +107,86 @@ internal object AccountCryptoCurrencyStatusFinder {
|
|||
derivationPath: Network.DerivationPath,
|
||||
contractAddress: String?,
|
||||
): AccountCryptoCurrencyStatus? {
|
||||
return accountStatusList.getExpectedAccountStatuses(
|
||||
val accountList = accountStatusList.toAccountList().getOrNull() ?: return null
|
||||
val accountCurrency = invoke(
|
||||
accountList = accountList,
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
contractAddress = contractAddress,
|
||||
) ?: return null
|
||||
|
||||
return accountStatusList.findStatus(accountCurrency)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region AccountCryptoCurrency methods
|
||||
|
||||
/**
|
||||
* Retrieves the [AccountCryptoCurrency] for the specified [currency] from the given [accountList].
|
||||
*
|
||||
* @param accountList the list of accounts to search within.
|
||||
* @param currency the cryptocurrency to be retrieved.
|
||||
* @return the [AccountCryptoCurrency] if found, otherwise null.
|
||||
*/
|
||||
operator fun invoke(accountList: AccountList, currency: CryptoCurrency): AccountCryptoCurrency? {
|
||||
return invoke(
|
||||
accountList = accountList,
|
||||
currencyId = currency.id,
|
||||
network = currency.network,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the [AccountCryptoCurrency] for the specified [currencyId] and [network]
|
||||
* from the given [accountList].
|
||||
*
|
||||
* @param accountList the list of accounts to search within.
|
||||
* @param currencyId the ID of the cryptocurrency to be retrieved.
|
||||
* @param network the network associated with the cryptocurrency.
|
||||
* @return the [AccountCryptoCurrency] if found, otherwise null.
|
||||
*/
|
||||
operator fun invoke(
|
||||
accountList: AccountList,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
network: Network?,
|
||||
): AccountCryptoCurrency? {
|
||||
return accountList.getExpectedAccounts(network)
|
||||
.asSequence()
|
||||
.filterIsInstance<Account.CryptoPortfolio>()
|
||||
.mapNotNull { account ->
|
||||
val currency = account.cryptoCurrencies.firstOrNull { it.id == currencyId }
|
||||
?: return@mapNotNull null
|
||||
|
||||
AccountCryptoCurrency(account = account, cryptoCurrency = currency)
|
||||
}
|
||||
.firstOrNull()
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the [AccountCryptoCurrency] for the specified [networkId], [derivationPath],
|
||||
* and optional [contractAddress] from the given [accountList].
|
||||
*
|
||||
* @param accountList the list of accounts to search within.
|
||||
* @param networkId the ID of the network associated with the cryptocurrency.
|
||||
* @param derivationPath the derivation path of the account.
|
||||
* @param contractAddress the optional contract address of the token (if applicable).
|
||||
* @return the [AccountCryptoCurrency] if found, otherwise null.
|
||||
*/
|
||||
operator fun invoke(
|
||||
accountList: AccountList,
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
contractAddress: String?,
|
||||
): AccountCryptoCurrency? {
|
||||
return accountList.getExpectedAccounts(
|
||||
rawNetworkId = networkId.rawId.value,
|
||||
derivationPath = derivationPath,
|
||||
)
|
||||
.asSequence()
|
||||
.filterCryptoPortfolio()
|
||||
.mapNotNull { accountStatus ->
|
||||
val status = accountStatus.flattenCurrencies().firstOrNull {
|
||||
val currency = it.currency
|
||||
.filterIsInstance<Account.CryptoPortfolio>()
|
||||
.mapNotNull { account ->
|
||||
val currency = account.cryptoCurrencies.firstOrNull { currency ->
|
||||
val isContractAddressMatch = contractAddress == null ||
|
||||
currency.id.contractAddress.equals(contractAddress, ignoreCase = true)
|
||||
|
||||
|
|
@ -122,74 +196,81 @@ internal object AccountCryptoCurrencyStatusFinder {
|
|||
}
|
||||
?: return@mapNotNull null
|
||||
|
||||
AccountCryptoCurrencyStatus(account = accountStatus.account, status = status)
|
||||
AccountCryptoCurrency(account = account, cryptoCurrency = currency)
|
||||
}
|
||||
.firstOrNull()
|
||||
}
|
||||
|
||||
private fun AccountStatusList.getExpectedAccountStatuses(network: Network?): List<AccountStatus> {
|
||||
return getExpectedAccountStatuses(rawNetworkId = network?.rawId, derivationPath = network?.derivationPath)
|
||||
// endregion
|
||||
|
||||
// region AccountStatusList helpers
|
||||
|
||||
private fun AccountStatusList.findStatus(accountCurrency: AccountCryptoCurrency): AccountCryptoCurrencyStatus? {
|
||||
val accountStatus = accountStatuses
|
||||
.filterCryptoPortfolio()
|
||||
.firstOrNull { it.account.accountId == accountCurrency.account.accountId }
|
||||
?: return null
|
||||
|
||||
val currencyStatus = accountStatus.flattenCurrencies()
|
||||
.firstOrNull { it.currency.id == accountCurrency.cryptoCurrency.id }
|
||||
?: return null
|
||||
|
||||
return AccountCryptoCurrencyStatus(account = accountCurrency.account, status = currencyStatus)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the expected account statuses based on the provided [rawNetworkId] and [derivationPath].
|
||||
* If either parameter is null, all account statuses are returned.
|
||||
* If both parameters are provided, it filters the accounts based on the derivation index.
|
||||
*
|
||||
* @param rawNetworkId the raw ID of the network to filter accounts by, can be null.
|
||||
* @param derivationPath the derivation path of the network to filter accounts by, can be null.
|
||||
* @return a list of [AccountStatus] that match the expected criteria.
|
||||
*/
|
||||
private fun AccountStatusList.getExpectedAccountStatuses(
|
||||
rawNetworkId: String?,
|
||||
derivationPath: Network.DerivationPath?,
|
||||
): List<AccountStatus> {
|
||||
val possibleAccountIndex = if (rawNetworkId != null && derivationPath != null) {
|
||||
getAccountIndexOrNull(rawNetworkId, derivationPath)
|
||||
} else {
|
||||
null
|
||||
private fun AccountStatusList.getExpectedAccountStatuses(networks: List<Network>): List<AccountStatus> {
|
||||
val possibleAccountIndexes = networks.mapNotNull { getAccountIndexOrNull(it.rawId, it.derivationPath) }
|
||||
|
||||
if (possibleAccountIndexes.isEmpty()) return accountStatuses
|
||||
|
||||
val filteredStatuses = accountStatuses.filter { accountStatus ->
|
||||
val cryptoPortfolio = accountStatus.account as? Account.CryptoPortfolio ?: return@filter false
|
||||
cryptoPortfolio.derivationIndex.value in possibleAccountIndexes
|
||||
}
|
||||
|
||||
return filteredStatuses + listOf(mainAccount)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region AccountList helpers
|
||||
|
||||
private fun AccountList.getExpectedAccounts(network: Network?): List<Account> {
|
||||
return getExpectedAccounts(rawNetworkId = network?.rawId, derivationPath = network?.derivationPath)
|
||||
}
|
||||
|
||||
private fun AccountList.getExpectedAccounts(
|
||||
rawNetworkId: String?,
|
||||
derivationPath: Network.DerivationPath?,
|
||||
): List<Account> {
|
||||
val possibleAccountIndex = getAccountIndexOrNull(rawNetworkId, derivationPath)
|
||||
|
||||
return when (possibleAccountIndex) {
|
||||
// currency can be in any account
|
||||
null -> accountStatuses
|
||||
// currency only in the main account
|
||||
null -> accounts
|
||||
DerivationIndex.Main.value -> listOf(mainAccount)
|
||||
// currency only in the account with specific derivation index or in the main account
|
||||
else -> {
|
||||
val accountStatus = accountStatuses.firstOrNull { accountStatus ->
|
||||
val cryptoPortfolio = accountStatus.account as? Account.CryptoPortfolio ?: return@firstOrNull false
|
||||
|
||||
val account = accounts.firstOrNull { account ->
|
||||
val cryptoPortfolio = account as? Account.CryptoPortfolio ?: return@firstOrNull false
|
||||
cryptoPortfolio.derivationIndex.value == possibleAccountIndex
|
||||
}
|
||||
|
||||
listOfNotNull(accountStatus, mainAccount)
|
||||
listOfNotNull(account, mainAccount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun AccountStatusList.getExpectedAccountStatuses(networks: List<Network>): List<AccountStatus> {
|
||||
val possibleAccountIndexes = networks.mapNotNull { it.getAccountIndexOrNull() }
|
||||
// endregion
|
||||
|
||||
if (possibleAccountIndexes.isEmpty()) return this@getExpectedAccountStatuses.accountStatuses
|
||||
// region Common helpers
|
||||
|
||||
val accountStatuses = this@getExpectedAccountStatuses.accountStatuses.filter { accountStatus ->
|
||||
val cryptoPortfolio = accountStatus.account as? Account.CryptoPortfolio ?: return@filter false
|
||||
private fun getAccountIndexOrNull(rawNetworkId: String?, derivationPath: Network.DerivationPath?): Int? {
|
||||
if (rawNetworkId == null || derivationPath == null) return null
|
||||
|
||||
cryptoPortfolio.derivationIndex.value in possibleAccountIndexes
|
||||
}
|
||||
|
||||
return accountStatuses + listOf(mainAccount)
|
||||
}
|
||||
|
||||
private fun Network.getAccountIndexOrNull(): Int? {
|
||||
return getAccountIndexOrNull(rawNetworkId = rawId, derivationPath = derivationPath)
|
||||
}
|
||||
|
||||
private fun getAccountIndexOrNull(rawNetworkId: String, derivationPath: Network.DerivationPath): Int? {
|
||||
val blockchain = Blockchain.fromId(id = rawNetworkId)
|
||||
val recognizer = AccountNodeRecognizer(blockchain)
|
||||
|
||||
return recognizer.recognize(derivationPath)?.toInt()
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package com.tangem.domain.account.status.utils
|
||||
|
||||
import arrow.core.Option
|
||||
import arrow.core.raise.option
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
|
||||
/**
|
||||
* Extension functions for retrieving [AccountCryptoCurrencyStatus] from an [AccountStatusList].
|
||||
*
|
||||
* This object provides convenient extension functions to search and retrieve [AccountCryptoCurrencyStatus]
|
||||
* instances from an [AccountStatusList] using various parameters such as cryptocurrency ID and network.
|
||||
*
|
||||
* The primary difference from [AccountCryptoCurrencyOperations] is that this object works with
|
||||
* [AccountStatusList] and returns status information along with the account-currency association.
|
||||
*
|
||||
* Usage example:
|
||||
* ```
|
||||
* val accountStatusList: AccountStatusList? = ...
|
||||
* val result: Option<AccountCryptoCurrencyStatus> = accountStatusList.getAccountCryptoCurrencyStatus(currency)
|
||||
* result.fold(
|
||||
* ifEmpty = { /* handle not found */ },
|
||||
* ifSome = { accountCurrencyStatus -> /* use the found result */ }
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* @see AccountCryptoCurrencyStatus
|
||||
* @see AccountStatusList
|
||||
* @see AccountCryptoCurrencyOperations
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
object AccountCryptoCurrencyStatusOperations {
|
||||
|
||||
// region AccountStatusList
|
||||
|
||||
/**
|
||||
* Retrieves the [AccountCryptoCurrencyStatus] for the specified [currency] from this [AccountStatusList].
|
||||
*
|
||||
* @receiver the [AccountStatusList] to search within, can be null
|
||||
* @param currency the cryptocurrency whose account status association is to be retrieved
|
||||
* @return [Option] containing the [AccountCryptoCurrencyStatus] if found, or [Option.None] otherwise
|
||||
*/
|
||||
fun AccountStatusList?.getAccountCryptoCurrencyStatus(
|
||||
currency: CryptoCurrency,
|
||||
): Option<AccountCryptoCurrencyStatus> {
|
||||
return getAccountCryptoCurrencyStatus(currencyId = currency.id, network = currency.network)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the [AccountCryptoCurrencyStatus] for the specified [currencyId] and [network]
|
||||
* from this [AccountStatusList].
|
||||
*
|
||||
* @receiver the [AccountStatusList] to search within, can be null
|
||||
* @param currencyId the ID of the cryptocurrency whose account status association is to be retrieved
|
||||
* @param network the network associated with the cryptocurrency, can be null
|
||||
* @return [Option] containing the [AccountCryptoCurrencyStatus] if found, or [Option.None] otherwise
|
||||
*/
|
||||
fun AccountStatusList?.getAccountCryptoCurrencyStatus(
|
||||
currencyId: CryptoCurrency.ID,
|
||||
network: Network?,
|
||||
): Option<AccountCryptoCurrencyStatus> = option {
|
||||
val accountStatusList = this@getAccountCryptoCurrencyStatus
|
||||
|
||||
ensureNotNull(accountStatusList)
|
||||
|
||||
val accountCryptoCurrencyStatus = AccountCryptoCurrencyStatusFinder(
|
||||
accountStatusList = accountStatusList,
|
||||
currencyId = currencyId,
|
||||
network = network,
|
||||
)
|
||||
|
||||
ensureNotNull(accountCryptoCurrencyStatus)
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package com.tangem.domain.account.status.utils
|
||||
|
||||
import arrow.core.Option
|
||||
import arrow.core.toOption
|
||||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.status.utils.AccountCryptoCurrencyOperations.getAccountCryptoCurrency
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
|
||||
/**
|
||||
* Extension functions for retrieving [CryptoCurrency] from an [AccountList] or [Account.CryptoPortfolio].
|
||||
*
|
||||
* This object provides convenient extension functions to search and retrieve [CryptoCurrency] instances
|
||||
* from account-related data structures using various parameters such as cryptocurrency ID and network.
|
||||
*
|
||||
* Unlike [AccountCryptoCurrencyOperations], this object returns only the [CryptoCurrency] without
|
||||
* the associated account information.
|
||||
*
|
||||
* Usage example:
|
||||
* ```
|
||||
* val accountList: AccountList? = ...
|
||||
* val result: Option<CryptoCurrency> = accountList.getCryptoCurrency(currencyId, network)
|
||||
* result.fold(
|
||||
* ifEmpty = { /* handle not found */ },
|
||||
* ifSome = { currency -> /* use the found currency */ }
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* @see CryptoCurrency
|
||||
* @see AccountList
|
||||
* @see Account.CryptoPortfolio
|
||||
* @see AccountCryptoCurrencyOperations
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
object CryptoCurrencyOperations {
|
||||
|
||||
// region AccountList
|
||||
|
||||
/**
|
||||
* Retrieves the [CryptoCurrency] matching the specified [cryptoCurrency] from this [AccountList].
|
||||
*
|
||||
* @receiver the [AccountList] to search within, can be null
|
||||
* @param cryptoCurrency the cryptocurrency to match
|
||||
* @return [Option] containing the [CryptoCurrency] if found, or [Option.None] otherwise
|
||||
*/
|
||||
fun AccountList?.getCryptoCurrency(cryptoCurrency: CryptoCurrency): Option<CryptoCurrency> {
|
||||
return getCryptoCurrency(currencyId = cryptoCurrency.id, network = cryptoCurrency.network)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the [CryptoCurrency] for the specified [currencyId] and [network] from this [AccountList].
|
||||
*
|
||||
* @receiver the [AccountList] to search within, can be null
|
||||
* @param currencyId the ID of the cryptocurrency to be retrieved
|
||||
* @param network the network associated with the cryptocurrency, can be null
|
||||
* @return [Option] containing the [CryptoCurrency] if found, or [Option.None] otherwise
|
||||
*/
|
||||
fun AccountList?.getCryptoCurrency(currencyId: CryptoCurrency.ID, network: Network?): Option<CryptoCurrency> {
|
||||
return getAccountCryptoCurrency(currencyId, network)
|
||||
.map { it.cryptoCurrency }
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Account.CryptoPortfolio
|
||||
|
||||
/**
|
||||
* Retrieves the [CryptoCurrency] matching the specified [currencyId] from this [Account.CryptoPortfolio].
|
||||
*
|
||||
* @receiver the [Account.CryptoPortfolio] to search within
|
||||
* @param currencyId the ID of the cryptocurrency to be retrieved
|
||||
* @return [Option] containing the [CryptoCurrency] if found, or [Option.None] otherwise
|
||||
*/
|
||||
fun Account.CryptoPortfolio.getCryptoCurrency(currencyId: CryptoCurrency.ID): Option<CryptoCurrency> {
|
||||
return cryptoCurrencies.firstOrNull { it.id == currencyId }.toOption()
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package com.tangem.domain.account.status.utils
|
||||
|
||||
import arrow.core.Option
|
||||
import arrow.core.toOption
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatus
|
||||
import com.tangem.domain.account.status.utils.AccountCryptoCurrencyStatusOperations.getAccountCryptoCurrencyStatus
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.network.Network
|
||||
|
||||
/**
|
||||
* Extension functions for retrieving [CryptoCurrencyStatus] from an [AccountStatusList] or
|
||||
* [AccountStatus.CryptoPortfolio].
|
||||
*
|
||||
* This object provides convenient extension functions to search and retrieve [CryptoCurrencyStatus]
|
||||
* instances from account status-related data structures using various parameters such as cryptocurrency ID
|
||||
* and network.
|
||||
*
|
||||
* Unlike [AccountCryptoCurrencyStatusOperations], this object returns only the [CryptoCurrencyStatus] without
|
||||
* the associated account information.
|
||||
*
|
||||
* Usage example:
|
||||
* ```
|
||||
* val accountStatusList: AccountStatusList? = ...
|
||||
* val result: Option<CryptoCurrencyStatus> = accountStatusList.getCryptoCurrencyStatus(currency)
|
||||
* result.fold(
|
||||
* ifEmpty = { /* handle not found */ },
|
||||
* ifSome = { status -> /* use the found status */ }
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* @see CryptoCurrencyStatus
|
||||
* @see AccountStatusList
|
||||
* @see AccountStatus.CryptoPortfolio
|
||||
* @see AccountCryptoCurrencyStatusOperations
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
object CryptoCurrencyStatusOperations {
|
||||
|
||||
// region AccountStatusList
|
||||
|
||||
/**
|
||||
* Retrieves the [CryptoCurrencyStatus] for the specified [currency] from this [AccountStatusList].
|
||||
*
|
||||
* @receiver the [AccountStatusList] to search within, can be null
|
||||
* @param currency the cryptocurrency whose status is to be retrieved
|
||||
* @return [Option] containing the [CryptoCurrencyStatus] if found, or [Option.None] otherwise
|
||||
*/
|
||||
fun AccountStatusList?.getCryptoCurrencyStatus(currency: CryptoCurrency): Option<CryptoCurrencyStatus> {
|
||||
return getCryptoCurrencyStatus(currencyId = currency.id, network = currency.network)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the [CryptoCurrencyStatus] for the specified [currencyId] and [network]
|
||||
* from this [AccountStatusList].
|
||||
*
|
||||
* @receiver the [AccountStatusList] to search within, can be null
|
||||
* @param currencyId the ID of the cryptocurrency whose status is to be retrieved
|
||||
* @param network the network associated with the cryptocurrency, can be null
|
||||
* @return [Option] containing the [CryptoCurrencyStatus] if found, or [Option.None] otherwise
|
||||
*/
|
||||
fun AccountStatusList?.getCryptoCurrencyStatus(
|
||||
currencyId: CryptoCurrency.ID,
|
||||
network: Network?,
|
||||
): Option<CryptoCurrencyStatus> {
|
||||
return getAccountCryptoCurrencyStatus(currencyId = currencyId, network = network)
|
||||
.map(AccountCryptoCurrencyStatus::status)
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region AccountStatus.CryptoPortfolio
|
||||
|
||||
/**
|
||||
* Retrieves the [CryptoCurrencyStatus] for the specified [currencyId]
|
||||
* from this [AccountStatus.CryptoPortfolio].
|
||||
*
|
||||
* @receiver the [AccountStatus.CryptoPortfolio] to search within
|
||||
* @param currencyId the ID of the cryptocurrency whose status is to be retrieved
|
||||
* @return [Option] containing the [CryptoCurrencyStatus] if found, or [Option.None] otherwise
|
||||
*/
|
||||
fun AccountStatus.CryptoPortfolio.getCryptoCurrencyStatus(
|
||||
currencyId: CryptoCurrency.ID,
|
||||
): Option<CryptoCurrencyStatus> {
|
||||
return flattenCurrencies().firstOrNull { it.currency.id == currencyId }.toOption()
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
|
@ -7,11 +7,10 @@ import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatus
|
|||
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.core.utils.lceLoading
|
||||
import com.tangem.domain.models.TokensGroupType
|
||||
import com.tangem.domain.models.TokensSortType
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.account.*
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
|
|
@ -19,7 +18,10 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.test.core.assertNone
|
||||
import com.tangem.test.core.assertSome
|
||||
import com.tangem.test.core.getEmittedValues
|
||||
import io.mockk.*
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerifyOrder
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
|
|
@ -78,9 +80,15 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns listOf(accountStatus)
|
||||
}
|
||||
val accountStatusList = AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = listOf(accountStatus),
|
||||
totalAccounts = 1,
|
||||
totalArchivedAccounts = 0,
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortType = TokensSortType.NONE,
|
||||
groupType = TokensGroupType.NONE,
|
||||
)
|
||||
|
||||
coEvery { supplier.getSyncOrNull(supplierParams) } returns accountStatusList
|
||||
|
||||
|
|
@ -101,10 +109,14 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
|
||||
val account = mockk<Account.CryptoPortfolio>(relaxed = true) {
|
||||
every { this@mockk.derivationIndex } returns DerivationIndex(1).getOrNull()!!
|
||||
every { this@mockk.cryptoCurrencies } returns listOf(currency)
|
||||
}
|
||||
val derivationIndex = DerivationIndex(1).getOrNull()!!
|
||||
val account = Account.CryptoPortfolio(
|
||||
accountId = AccountId.forCryptoPortfolio(userWalletId, derivationIndex),
|
||||
accountName = AccountName("Test Account").getOrNull()!!,
|
||||
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
|
||||
derivationIndex = derivationIndex,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val currencyStatus = CryptoCurrencyStatus(currency = currency, value = CryptoCurrencyStatus.Loading)
|
||||
val accountStatus = AccountStatus.CryptoPortfolio(
|
||||
account = account,
|
||||
|
|
@ -116,9 +128,15 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns listOf(mainAccountStatus, accountStatus, mockk())
|
||||
}
|
||||
val accountStatusList = AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = listOf(mainAccountStatus, accountStatus),
|
||||
totalAccounts = 2,
|
||||
totalArchivedAccounts = 0,
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortType = TokensSortType.NONE,
|
||||
groupType = TokensGroupType.NONE,
|
||||
)
|
||||
|
||||
coEvery { supplier.getSyncOrNull(supplierParams) } returns accountStatusList
|
||||
|
||||
|
|
@ -139,9 +157,10 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
@Test
|
||||
fun `invokeSync returns Some if network is null`() = runTest {
|
||||
// Arrange
|
||||
val account = mockk<Account.CryptoPortfolio>(relaxed = true) {
|
||||
every { this@mockk.cryptoCurrencies } returns listOf(currency)
|
||||
}
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val currencyStatus = CryptoCurrencyStatus(currency = currency, value = CryptoCurrencyStatus.Loading)
|
||||
val accountStatus = AccountStatus.CryptoPortfolio(
|
||||
account = account,
|
||||
|
|
@ -153,9 +172,15 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns listOf(accountStatus)
|
||||
}
|
||||
val accountStatusList = AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = listOf(accountStatus),
|
||||
totalAccounts = 1,
|
||||
totalArchivedAccounts = 0,
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortType = TokensSortType.NONE,
|
||||
groupType = TokensGroupType.NONE,
|
||||
)
|
||||
|
||||
coEvery { supplier.getSyncOrNull(supplierParams) } returns accountStatusList
|
||||
|
||||
|
|
@ -197,9 +222,15 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns listOf(accountStatus)
|
||||
}
|
||||
val accountStatusList = AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = listOf(accountStatus),
|
||||
totalAccounts = 1,
|
||||
totalArchivedAccounts = 0,
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortType = TokensSortType.NONE,
|
||||
groupType = TokensGroupType.NONE,
|
||||
)
|
||||
|
||||
coEvery { supplier(supplierParams) } returns flowOf(accountStatusList)
|
||||
|
||||
|
|
@ -221,10 +252,14 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
|
||||
val account = mockk<Account.CryptoPortfolio>(relaxed = true) {
|
||||
every { this@mockk.derivationIndex } returns DerivationIndex(1).getOrNull()!!
|
||||
every { this@mockk.cryptoCurrencies } returns listOf(currency)
|
||||
}
|
||||
val derivationIndex = DerivationIndex(1).getOrNull()!!
|
||||
val account = Account.CryptoPortfolio(
|
||||
accountId = AccountId.forCryptoPortfolio(userWalletId, derivationIndex),
|
||||
accountName = AccountName("Test Account").getOrNull()!!,
|
||||
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
|
||||
derivationIndex = derivationIndex,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val currencyStatus = CryptoCurrencyStatus(currency = currency, value = CryptoCurrencyStatus.Loading)
|
||||
val accountStatus = AccountStatus.CryptoPortfolio(
|
||||
account = account,
|
||||
|
|
@ -236,9 +271,15 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns listOf(mainAccountStatus, accountStatus, mockk())
|
||||
}
|
||||
val accountStatusList = AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = listOf(mainAccountStatus, accountStatus),
|
||||
totalAccounts = 2,
|
||||
totalArchivedAccounts = 0,
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortType = TokensSortType.NONE,
|
||||
groupType = TokensGroupType.NONE,
|
||||
)
|
||||
|
||||
coEvery { supplier(supplierParams) } returns flowOf(accountStatusList)
|
||||
|
||||
|
|
@ -256,9 +297,10 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
@Test
|
||||
fun `invoke returns data if network is null`() = runTest {
|
||||
// Arrange
|
||||
val account = mockk<Account.CryptoPortfolio>(relaxed = true) {
|
||||
every { this@mockk.cryptoCurrencies } returns listOf(currency)
|
||||
}
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val currencyStatus = CryptoCurrencyStatus(currency = currency, value = CryptoCurrencyStatus.Loading)
|
||||
val accountStatus = AccountStatus.CryptoPortfolio(
|
||||
account = account,
|
||||
|
|
@ -270,9 +312,15 @@ class GetAccountCurrencyStatusUseCaseTest {
|
|||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
|
||||
val accountStatusList = mockk<AccountStatusList>(relaxed = true) {
|
||||
every { this@mockk.accountStatuses } returns listOf(accountStatus)
|
||||
}
|
||||
val accountStatusList = AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = listOf(accountStatus),
|
||||
totalAccounts = 1,
|
||||
totalArchivedAccounts = 0,
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortType = TokensSortType.NONE,
|
||||
groupType = TokensGroupType.NONE,
|
||||
)
|
||||
|
||||
coEvery { supplier(supplierParams) } returns flowOf(accountStatusList)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,169 @@
|
|||
package com.tangem.domain.account.status.utils
|
||||
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrency
|
||||
import com.tangem.domain.account.status.utils.AccountCryptoCurrencyOperations.getAccountCryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.test.core.assertNone
|
||||
import com.tangem.test.core.assertSome
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
/**
|
||||
* Tests for [AccountCryptoCurrencyOperations].
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class AccountCryptoCurrencyOperationsTest {
|
||||
|
||||
private val cryptoCurrencyFactory = MockCryptoCurrencyFactory()
|
||||
private val userWalletId = UserWalletId("011")
|
||||
private val currency = cryptoCurrencyFactory.ethereum
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetAccountCryptoCurrencyByCurrency {
|
||||
|
||||
@Test
|
||||
fun `returns None when AccountList is null`() {
|
||||
// Arrange
|
||||
val accountList: AccountList? = null
|
||||
// Act
|
||||
val result = accountList.getAccountCryptoCurrency(currency)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns None when currency is not found in AccountList`() {
|
||||
// Arrange
|
||||
val accountList = AccountList.empty(userWalletId)
|
||||
// Act
|
||||
val result = accountList.getAccountCryptoCurrency(currency)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency is found in AccountList`() {
|
||||
// Arrange
|
||||
val accountList = AccountList.empty(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val expected = AccountCryptoCurrency(
|
||||
account = accountList.mainAccount,
|
||||
cryptoCurrency = currency,
|
||||
)
|
||||
// Act
|
||||
val result = accountList.getAccountCryptoCurrency(currency)
|
||||
// Assert
|
||||
assertSome(result, expected)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetAccountCryptoCurrencyByCurrencyIdAndNetwork {
|
||||
|
||||
@Test
|
||||
fun `returns None when AccountList is null`() {
|
||||
// Arrange
|
||||
val accountList: AccountList? = null
|
||||
// Act
|
||||
val result = accountList.getAccountCryptoCurrency(
|
||||
currencyId = currency.id,
|
||||
network = currency.network,
|
||||
)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns None when currency id is not found`() {
|
||||
// Arrange
|
||||
val accountList = AccountList.empty(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val otherCurrencyId = CryptoCurrency.ID(
|
||||
prefix = CryptoCurrency.ID.Prefix.COIN_PREFIX,
|
||||
body = CryptoCurrency.ID.Body.NetworkId("bitcoin"),
|
||||
suffix = CryptoCurrency.ID.Suffix.RawID("bitcoin"),
|
||||
)
|
||||
// Act
|
||||
val result = accountList.getAccountCryptoCurrency(
|
||||
currencyId = otherCurrencyId,
|
||||
network = currency.network,
|
||||
)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency id is found with null network`() {
|
||||
// Arrange
|
||||
val accountList = AccountList.empty(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val expected = AccountCryptoCurrency(
|
||||
account = accountList.mainAccount,
|
||||
cryptoCurrency = currency,
|
||||
)
|
||||
// Act
|
||||
val result = accountList.getAccountCryptoCurrency(
|
||||
currencyId = currency.id,
|
||||
network = null,
|
||||
)
|
||||
// Assert
|
||||
assertSome(result, expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency id and network match`() {
|
||||
// Arrange
|
||||
val accountList = AccountList.empty(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val expected = AccountCryptoCurrency(
|
||||
account = accountList.mainAccount,
|
||||
cryptoCurrency = currency,
|
||||
)
|
||||
// Act
|
||||
val result = accountList.getAccountCryptoCurrency(
|
||||
currencyId = currency.id,
|
||||
network = currency.network,
|
||||
)
|
||||
// Assert
|
||||
assertSome(result, expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some with first matching currency when multiple currencies exist`() {
|
||||
// Arrange
|
||||
val currencies = cryptoCurrencyFactory.ethereumAndStellar
|
||||
val accountList = AccountList.empty(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = currencies,
|
||||
)
|
||||
val targetCurrency = currencies.first()
|
||||
val expected = AccountCryptoCurrency(
|
||||
account = accountList.mainAccount,
|
||||
cryptoCurrency = targetCurrency,
|
||||
)
|
||||
// Act
|
||||
val result = accountList.getAccountCryptoCurrency(
|
||||
currencyId = targetCurrency.id,
|
||||
network = targetCurrency.network,
|
||||
)
|
||||
// Assert
|
||||
assertSome(result, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
package com.tangem.domain.account.status.utils
|
||||
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatus
|
||||
import com.tangem.domain.account.status.utils.AccountCryptoCurrencyStatusOperations.getAccountCryptoCurrencyStatus
|
||||
import com.tangem.domain.core.utils.lceLoading
|
||||
import com.tangem.domain.models.TokensGroupType
|
||||
import com.tangem.domain.models.TokensSortType
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.test.core.assertNone
|
||||
import com.tangem.test.core.assertSome
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
/**
|
||||
* Tests for [AccountCryptoCurrencyStatusOperations].
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class AccountCryptoCurrencyStatusOperationsTest {
|
||||
|
||||
private val cryptoCurrencyFactory = MockCryptoCurrencyFactory()
|
||||
private val userWalletId = UserWalletId("011")
|
||||
private val currency = cryptoCurrencyFactory.ethereum
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetAccountCryptoCurrencyStatusByCurrency {
|
||||
|
||||
@Test
|
||||
fun `returns None when AccountStatusList is null`() {
|
||||
val accountStatusList: AccountStatusList? = null
|
||||
val result = accountStatusList.getAccountCryptoCurrencyStatus(currency)
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns None when currency is not found in AccountStatusList`() {
|
||||
val accountStatusList = createAccountStatusList(currencies = emptyList())
|
||||
val result = accountStatusList.getAccountCryptoCurrencyStatus(currency)
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency is found in AccountStatusList`() {
|
||||
val currencyStatus = CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
)
|
||||
val accountStatusList = createAccountStatusList(
|
||||
currencies = listOf(currency),
|
||||
currencyStatuses = listOf(currencyStatus),
|
||||
)
|
||||
val expected = AccountCryptoCurrencyStatus(
|
||||
account = accountStatusList.mainAccount.account,
|
||||
status = currencyStatus,
|
||||
)
|
||||
val result = accountStatusList.getAccountCryptoCurrencyStatus(currency)
|
||||
assertSome(result, expected)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetAccountCryptoCurrencyStatusByCurrencyIdAndNetwork {
|
||||
|
||||
@Test
|
||||
fun `returns None when AccountStatusList is null`() {
|
||||
val accountStatusList: AccountStatusList? = null
|
||||
val result = accountStatusList.getAccountCryptoCurrencyStatus(
|
||||
currencyId = currency.id,
|
||||
network = currency.network,
|
||||
)
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns None when currency id is not found`() {
|
||||
val currencyStatus = CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
)
|
||||
val accountStatusList = createAccountStatusList(
|
||||
currencies = listOf(currency),
|
||||
currencyStatuses = listOf(currencyStatus),
|
||||
)
|
||||
val otherCurrencyId = CryptoCurrency.ID(
|
||||
prefix = CryptoCurrency.ID.Prefix.COIN_PREFIX,
|
||||
body = CryptoCurrency.ID.Body.NetworkId("bitcoin"),
|
||||
suffix = CryptoCurrency.ID.Suffix.RawID("bitcoin"),
|
||||
)
|
||||
val result = accountStatusList.getAccountCryptoCurrencyStatus(
|
||||
currencyId = otherCurrencyId,
|
||||
network = currency.network,
|
||||
)
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency id is found with null network`() {
|
||||
val currencyStatus = CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
)
|
||||
val accountStatusList = createAccountStatusList(
|
||||
currencies = listOf(currency),
|
||||
currencyStatuses = listOf(currencyStatus),
|
||||
)
|
||||
val expected = AccountCryptoCurrencyStatus(
|
||||
account = accountStatusList.mainAccount.account,
|
||||
status = currencyStatus,
|
||||
)
|
||||
val result = accountStatusList.getAccountCryptoCurrencyStatus(
|
||||
currencyId = currency.id,
|
||||
network = null,
|
||||
)
|
||||
assertSome(result, expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency id and network match`() {
|
||||
val currencyStatus = CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
)
|
||||
val accountStatusList = createAccountStatusList(
|
||||
currencies = listOf(currency),
|
||||
currencyStatuses = listOf(currencyStatus),
|
||||
)
|
||||
val expected = AccountCryptoCurrencyStatus(
|
||||
account = accountStatusList.mainAccount.account,
|
||||
status = currencyStatus,
|
||||
)
|
||||
val result = accountStatusList.getAccountCryptoCurrencyStatus(
|
||||
currencyId = currency.id,
|
||||
network = currency.network,
|
||||
)
|
||||
assertSome(result, expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some with first matching currency when multiple currencies exist`() {
|
||||
val currencies = cryptoCurrencyFactory.ethereumAndStellar
|
||||
val currencyStatuses = currencies.map {
|
||||
CryptoCurrencyStatus(currency = it, value = CryptoCurrencyStatus.Loading)
|
||||
}
|
||||
val accountStatusList = createAccountStatusList(
|
||||
currencies = currencies,
|
||||
currencyStatuses = currencyStatuses,
|
||||
)
|
||||
val targetCurrency = currencies.first()
|
||||
val expected = AccountCryptoCurrencyStatus(
|
||||
account = accountStatusList.mainAccount.account,
|
||||
status = currencyStatuses.first(),
|
||||
)
|
||||
val result = accountStatusList.getAccountCryptoCurrencyStatus(
|
||||
currencyId = targetCurrency.id,
|
||||
network = targetCurrency.network,
|
||||
)
|
||||
assertSome(result, expected)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createAccountStatusList(
|
||||
currencies: List<CryptoCurrency>,
|
||||
currencyStatuses: List<CryptoCurrencyStatus> = emptyList(),
|
||||
): AccountStatusList {
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = currencies,
|
||||
)
|
||||
val tokenList = if (currencyStatuses.isEmpty()) {
|
||||
TokenList.Empty
|
||||
} else {
|
||||
TokenList.Ungrouped(
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortedBy = TokensSortType.NONE,
|
||||
currencies = currencyStatuses,
|
||||
)
|
||||
}
|
||||
val accountStatus = AccountStatus.CryptoPortfolio(
|
||||
account = account,
|
||||
tokenList = tokenList,
|
||||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
return AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = listOf(accountStatus),
|
||||
totalAccounts = 1,
|
||||
totalArchivedAccounts = 0,
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortType = TokensSortType.NONE,
|
||||
groupType = TokensGroupType.NONE,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
package com.tangem.domain.account.status.utils
|
||||
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.status.utils.CryptoCurrencyOperations.getCryptoCurrency
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.test.core.assertNone
|
||||
import com.tangem.test.core.assertSome
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
/**
|
||||
* Tests for [CryptoCurrencyOperations].
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class CryptoCurrencyOperationsTest {
|
||||
|
||||
private val cryptoCurrencyFactory = MockCryptoCurrencyFactory()
|
||||
private val userWalletId = UserWalletId("011")
|
||||
private val currency = cryptoCurrencyFactory.ethereum
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetCryptoCurrencyFromAccountListByCurrency {
|
||||
|
||||
@Test
|
||||
fun `returns None when currency is not found in AccountList`() {
|
||||
// Arrange
|
||||
val accountList = AccountList.empty(userWalletId)
|
||||
// Act
|
||||
val result = accountList.getCryptoCurrency(currency)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency is found in AccountList`() {
|
||||
// Arrange
|
||||
val accountList = AccountList.empty(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
// Act
|
||||
val result = accountList.getCryptoCurrency(currency)
|
||||
// Assert
|
||||
assertSome(result, currency)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetCryptoCurrencyFromAccountListByCurrencyIdAndNetwork {
|
||||
|
||||
@Test
|
||||
fun `returns None when AccountList is null`() {
|
||||
// Arrange
|
||||
val accountList: AccountList? = null
|
||||
// Act
|
||||
val result = accountList.getCryptoCurrency(
|
||||
currencyId = currency.id,
|
||||
network = currency.network,
|
||||
)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns None when currency id is not found`() {
|
||||
// Arrange
|
||||
val accountList = AccountList.empty(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val otherCurrencyId = CryptoCurrency.ID(
|
||||
prefix = CryptoCurrency.ID.Prefix.COIN_PREFIX,
|
||||
body = CryptoCurrency.ID.Body.NetworkId("bitcoin"),
|
||||
suffix = CryptoCurrency.ID.Suffix.RawID("bitcoin"),
|
||||
)
|
||||
// Act
|
||||
val result = accountList.getCryptoCurrency(
|
||||
currencyId = otherCurrencyId,
|
||||
network = currency.network,
|
||||
)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency id is found with null network`() {
|
||||
// Arrange
|
||||
val accountList = AccountList.empty(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
// Act
|
||||
val result = accountList.getCryptoCurrency(
|
||||
currencyId = currency.id,
|
||||
network = null,
|
||||
)
|
||||
// Assert
|
||||
assertSome(result, currency)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency id and network match`() {
|
||||
// Arrange
|
||||
val accountList = AccountList.empty(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
// Act
|
||||
val result = accountList.getCryptoCurrency(
|
||||
currencyId = currency.id,
|
||||
network = currency.network,
|
||||
)
|
||||
// Assert
|
||||
assertSome(result, currency)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some with first matching currency when multiple currencies exist`() {
|
||||
// Arrange
|
||||
val currencies = cryptoCurrencyFactory.ethereumAndStellar
|
||||
val accountList = AccountList.empty(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = currencies,
|
||||
)
|
||||
val targetCurrency = currencies.first()
|
||||
// Act
|
||||
val result = accountList.getCryptoCurrency(
|
||||
currencyId = targetCurrency.id,
|
||||
network = targetCurrency.network,
|
||||
)
|
||||
// Assert
|
||||
assertSome(result, targetCurrency)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetCryptoCurrencyFromCryptoPortfolio {
|
||||
|
||||
@Test
|
||||
fun `returns None when currency id is not found in CryptoPortfolio`() {
|
||||
// Arrange
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val otherCurrencyId = CryptoCurrency.ID(
|
||||
prefix = CryptoCurrency.ID.Prefix.COIN_PREFIX,
|
||||
body = CryptoCurrency.ID.Body.NetworkId("bitcoin"),
|
||||
suffix = CryptoCurrency.ID.Suffix.RawID("bitcoin"),
|
||||
)
|
||||
// Act
|
||||
val result = account.getCryptoCurrency(otherCurrencyId)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency id is found in CryptoPortfolio`() {
|
||||
// Arrange
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
// Act
|
||||
val result = account.getCryptoCurrency(currency.id)
|
||||
// Assert
|
||||
assertSome(result, currency)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns None when CryptoPortfolio has no currencies`() {
|
||||
// Arrange
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = emptyList(),
|
||||
)
|
||||
// Act
|
||||
val result = account.getCryptoCurrency(currency.id)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some with matching currency when multiple currencies exist`() {
|
||||
// Arrange
|
||||
val currencies = cryptoCurrencyFactory.ethereumAndStellar
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = currencies,
|
||||
)
|
||||
val targetCurrency = currencies.last()
|
||||
// Act
|
||||
val result = account.getCryptoCurrency(targetCurrency.id)
|
||||
// Assert
|
||||
assertSome(result, targetCurrency)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
package com.tangem.domain.account.status.utils
|
||||
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.utils.CryptoCurrencyStatusOperations.getCryptoCurrencyStatus
|
||||
import com.tangem.domain.core.utils.lceLoading
|
||||
import com.tangem.domain.models.TokensGroupType
|
||||
import com.tangem.domain.models.TokensSortType
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.test.core.assertNone
|
||||
import com.tangem.test.core.assertSome
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
/**
|
||||
* Tests for [CryptoCurrencyStatusOperations].
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class CryptoCurrencyStatusOperationsTest {
|
||||
|
||||
private val cryptoCurrencyFactory = MockCryptoCurrencyFactory()
|
||||
private val userWalletId = UserWalletId("011")
|
||||
private val currency = cryptoCurrencyFactory.ethereum
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetCryptoCurrencyStatusFromAccountStatusListByCurrency {
|
||||
|
||||
@Test
|
||||
fun `returns None when AccountStatusList is null`() {
|
||||
// Arrange
|
||||
val accountStatusList: AccountStatusList? = null
|
||||
// Act
|
||||
val result = accountStatusList.getCryptoCurrencyStatus(currency)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns None when currency is not found in AccountStatusList`() {
|
||||
// Arrange
|
||||
val accountStatusList = createAccountStatusList(currencies = emptyList())
|
||||
// Act
|
||||
val result = accountStatusList.getCryptoCurrencyStatus(currency)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency is found in AccountStatusList`() {
|
||||
// Arrange
|
||||
val currencyStatus = CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
)
|
||||
val accountStatusList = createAccountStatusList(
|
||||
currencies = listOf(currency),
|
||||
currencyStatuses = listOf(currencyStatus),
|
||||
)
|
||||
// Act
|
||||
val result = accountStatusList.getCryptoCurrencyStatus(currency)
|
||||
// Assert
|
||||
assertSome(result, currencyStatus)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetCryptoCurrencyStatusFromAccountStatusListByCurrencyIdAndNetwork {
|
||||
|
||||
@Test
|
||||
fun `returns None when AccountStatusList is null`() {
|
||||
// Arrange
|
||||
val accountStatusList: AccountStatusList? = null
|
||||
// Act
|
||||
val result = accountStatusList.getCryptoCurrencyStatus(
|
||||
currencyId = currency.id,
|
||||
network = currency.network,
|
||||
)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns None when currency id is not found`() {
|
||||
// Arrange
|
||||
val currencyStatus = CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
)
|
||||
val accountStatusList = createAccountStatusList(
|
||||
currencies = listOf(currency),
|
||||
currencyStatuses = listOf(currencyStatus),
|
||||
)
|
||||
val otherCurrencyId = CryptoCurrency.ID(
|
||||
prefix = CryptoCurrency.ID.Prefix.COIN_PREFIX,
|
||||
body = CryptoCurrency.ID.Body.NetworkId("bitcoin"),
|
||||
suffix = CryptoCurrency.ID.Suffix.RawID("bitcoin"),
|
||||
)
|
||||
// Act
|
||||
val result = accountStatusList.getCryptoCurrencyStatus(
|
||||
currencyId = otherCurrencyId,
|
||||
network = currency.network,
|
||||
)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency id is found with null network`() {
|
||||
// Arrange
|
||||
val currencyStatus = CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
)
|
||||
val accountStatusList = createAccountStatusList(
|
||||
currencies = listOf(currency),
|
||||
currencyStatuses = listOf(currencyStatus),
|
||||
)
|
||||
// Act
|
||||
val result = accountStatusList.getCryptoCurrencyStatus(
|
||||
currencyId = currency.id,
|
||||
network = null,
|
||||
)
|
||||
// Assert
|
||||
assertSome(result, currencyStatus)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency id and network match`() {
|
||||
// Arrange
|
||||
val currencyStatus = CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
)
|
||||
val accountStatusList = createAccountStatusList(
|
||||
currencies = listOf(currency),
|
||||
currencyStatuses = listOf(currencyStatus),
|
||||
)
|
||||
// Act
|
||||
val result = accountStatusList.getCryptoCurrencyStatus(
|
||||
currencyId = currency.id,
|
||||
network = currency.network,
|
||||
)
|
||||
// Assert
|
||||
assertSome(result, currencyStatus)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some with first matching currency status when multiple currencies exist`() {
|
||||
// Arrange
|
||||
val currencies = cryptoCurrencyFactory.ethereumAndStellar
|
||||
val currencyStatuses = currencies.map {
|
||||
CryptoCurrencyStatus(currency = it, value = CryptoCurrencyStatus.Loading)
|
||||
}
|
||||
val accountStatusList = createAccountStatusList(
|
||||
currencies = currencies,
|
||||
currencyStatuses = currencyStatuses,
|
||||
)
|
||||
val targetCurrency = currencies.first()
|
||||
val expectedStatus = currencyStatuses.first()
|
||||
// Act
|
||||
val result = accountStatusList.getCryptoCurrencyStatus(
|
||||
currencyId = targetCurrency.id,
|
||||
network = targetCurrency.network,
|
||||
)
|
||||
// Assert
|
||||
assertSome(result, expectedStatus)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetCryptoCurrencyStatusFromCryptoPortfolio {
|
||||
|
||||
@Test
|
||||
fun `returns None when currency id is not found in CryptoPortfolio`() {
|
||||
// Arrange
|
||||
val currencyStatus = CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
)
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val accountStatus = AccountStatus.CryptoPortfolio(
|
||||
account = account,
|
||||
tokenList = TokenList.Ungrouped(
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortedBy = TokensSortType.NONE,
|
||||
currencies = listOf(currencyStatus),
|
||||
),
|
||||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
val otherCurrencyId = CryptoCurrency.ID(
|
||||
prefix = CryptoCurrency.ID.Prefix.COIN_PREFIX,
|
||||
body = CryptoCurrency.ID.Body.NetworkId("bitcoin"),
|
||||
suffix = CryptoCurrency.ID.Suffix.RawID("bitcoin"),
|
||||
)
|
||||
// Act
|
||||
val result = accountStatus.getCryptoCurrencyStatus(otherCurrencyId)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some when currency id is found in CryptoPortfolio`() {
|
||||
// Arrange
|
||||
val currencyStatus = CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
)
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = listOf(currency),
|
||||
)
|
||||
val accountStatus = AccountStatus.CryptoPortfolio(
|
||||
account = account,
|
||||
tokenList = TokenList.Ungrouped(
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortedBy = TokensSortType.NONE,
|
||||
currencies = listOf(currencyStatus),
|
||||
),
|
||||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
// Act
|
||||
val result = accountStatus.getCryptoCurrencyStatus(currency.id)
|
||||
// Assert
|
||||
assertSome(result, currencyStatus)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns None when CryptoPortfolio has empty token list`() {
|
||||
// Arrange
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = emptyList(),
|
||||
)
|
||||
val accountStatus = AccountStatus.CryptoPortfolio(
|
||||
account = account,
|
||||
tokenList = TokenList.Empty,
|
||||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
// Act
|
||||
val result = accountStatus.getCryptoCurrencyStatus(currency.id)
|
||||
// Assert
|
||||
assertNone(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns Some with matching currency status when multiple currencies exist`() {
|
||||
// Arrange
|
||||
val currencies = cryptoCurrencyFactory.ethereumAndStellar
|
||||
val currencyStatuses = currencies.map {
|
||||
CryptoCurrencyStatus(currency = it, value = CryptoCurrencyStatus.Loading)
|
||||
}
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = currencies,
|
||||
)
|
||||
val accountStatus = AccountStatus.CryptoPortfolio(
|
||||
account = account,
|
||||
tokenList = TokenList.Ungrouped(
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortedBy = TokensSortType.NONE,
|
||||
currencies = currencyStatuses,
|
||||
),
|
||||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
val targetCurrency = currencies.last()
|
||||
val expectedStatus = currencyStatuses.last()
|
||||
// Act
|
||||
val result = accountStatus.getCryptoCurrencyStatus(targetCurrency.id)
|
||||
// Assert
|
||||
assertSome(result, expectedStatus)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createAccountStatusList(
|
||||
currencies: List<CryptoCurrency>,
|
||||
currencyStatuses: List<CryptoCurrencyStatus> = emptyList(),
|
||||
): AccountStatusList {
|
||||
val account = Account.CryptoPortfolio.createMainAccount(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = currencies,
|
||||
)
|
||||
val tokenList = if (currencyStatuses.isEmpty()) {
|
||||
TokenList.Empty
|
||||
} else {
|
||||
TokenList.Ungrouped(
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortedBy = TokensSortType.NONE,
|
||||
currencies = currencyStatuses,
|
||||
)
|
||||
}
|
||||
val accountStatus = AccountStatus.CryptoPortfolio(
|
||||
account = account,
|
||||
tokenList = tokenList,
|
||||
priceChangeLce = lceLoading(),
|
||||
)
|
||||
return AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = listOf(accountStatus),
|
||||
totalAccounts = 1,
|
||||
totalArchivedAccounts = 0,
|
||||
totalFiatBalance = TotalFiatBalance.Loading,
|
||||
sortType = TokensSortType.NONE,
|
||||
groupType = TokensGroupType.NONE,
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue