Updated on 2026-08-14
This commit is contained in:
parent
06d1f35002
commit
6ed1946ac3
16 changed files with 191 additions and 220 deletions
|
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" ?>
|
|
||||||
<SmellBaseline>
|
|
||||||
<ManuallySuppressedIssues/>
|
|
||||||
<CurrentIssues>
|
|
||||||
<ID>MultilineLambdaItParameter:DefaultCustomTokensRepository.kt$DefaultCustomTokensRepository${ // TODO: refactor https://tangem.atlassian.net/browse/AND-10006\ if (it.isTestnet() || it in excludedBlockchains || it in hotWalletExcludedBlockchains) { return@mapNotNull null } networkFactory.create( blockchain = it, extraDerivationPath = null, userWallet = userWallet, ) }</ID>
|
|
||||||
<ID>MultilineLambdaItParameter:ManageTokensUpdateFetcher.kt$ManageTokensUpdateFetcher${ if (it.key == toUpdate[index].key) { Batch(it.key, updatedItems) } else { null } }</ID>
|
|
||||||
<ID>UnsafeCallOnNullableType:DefaultCustomTokensRepository.kt$DefaultCustomTokensRepository$coinNetwork.decimalCount!!</ID>
|
|
||||||
</CurrentIssues>
|
|
||||||
</SmellBaseline>
|
|
||||||
|
|
@ -13,11 +13,11 @@ import com.tangem.data.managetokens.utils.TokenAddressesConverter
|
||||||
import com.tangem.datasource.api.common.response.getOrThrow
|
import com.tangem.datasource.api.common.response.getOrThrow
|
||||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
|
||||||
import com.tangem.domain.card.common.extensions.canHandleBlockchain
|
import com.tangem.domain.card.common.extensions.canHandleBlockchain
|
||||||
import com.tangem.domain.card.common.extensions.hotWalletExcludedBlockchains
|
import com.tangem.domain.card.common.extensions.hotWalletExcludedBlockchains
|
||||||
import com.tangem.domain.card.common.extensions.supportedBlockchains
|
import com.tangem.domain.card.common.extensions.supportedBlockchains
|
||||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||||
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
import com.tangem.domain.managetokens.model.AddCustomTokenForm
|
import com.tangem.domain.managetokens.model.AddCustomTokenForm
|
||||||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
|
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
|
||||||
import com.tangem.domain.managetokens.repository.CustomTokensRepository
|
import com.tangem.domain.managetokens.repository.CustomTokensRepository
|
||||||
|
|
@ -32,7 +32,7 @@ import kotlinx.coroutines.withContext
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
internal class DefaultCustomTokensRepository(
|
internal class DefaultCustomTokensRepository(
|
||||||
private val tangemTechApi: TangemTechApi,
|
private val tangemTechApi: TangemTechApi,
|
||||||
private val userWalletsStore: UserWalletsStore,
|
private val userWalletsListRepository: UserWalletsListRepository,
|
||||||
private val userTokensResponseStore: UserTokensResponseStore,
|
private val userTokensResponseStore: UserTokensResponseStore,
|
||||||
private val walletManagersFacade: WalletManagersFacade,
|
private val walletManagersFacade: WalletManagersFacade,
|
||||||
private val excludedBlockchains: ExcludedBlockchains,
|
private val excludedBlockchains: ExcludedBlockchains,
|
||||||
|
|
@ -96,9 +96,8 @@ internal class DefaultCustomTokensRepository(
|
||||||
networkId: Network.ID,
|
networkId: Network.ID,
|
||||||
derivationPath: Network.DerivationPath,
|
derivationPath: Network.DerivationPath,
|
||||||
): CryptoCurrency.Token? = withContext(dispatchers.io) {
|
): CryptoCurrency.Token? = withContext(dispatchers.io) {
|
||||||
val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
|
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||||
"User wallet [$userWalletId] not found while finding token"
|
|
||||||
}
|
|
||||||
val network = requireNotNull(
|
val network = requireNotNull(
|
||||||
networkFactory.create(
|
networkFactory.create(
|
||||||
networkId = networkId,
|
networkId = networkId,
|
||||||
|
|
@ -138,7 +137,7 @@ internal class DefaultCustomTokensRepository(
|
||||||
rawId = CryptoCurrency.RawID(coin.id),
|
rawId = CryptoCurrency.RawID(coin.id),
|
||||||
name = coin.name,
|
name = coin.name,
|
||||||
symbol = coin.symbol,
|
symbol = coin.symbol,
|
||||||
decimals = coinNetwork.decimalCount!!.toInt(),
|
decimals = requireNotNull(coinNetwork.decimalCount).toInt(),
|
||||||
contractAddress = tokenAddress,
|
contractAddress = tokenAddress,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -152,9 +151,7 @@ internal class DefaultCustomTokensRepository(
|
||||||
networkId: Network.ID,
|
networkId: Network.ID,
|
||||||
derivationPath: Network.DerivationPath,
|
derivationPath: Network.DerivationPath,
|
||||||
): CryptoCurrency.Coin {
|
): CryptoCurrency.Coin {
|
||||||
val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
|
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||||
"User wallet [$userWalletId] not found while creating coin"
|
|
||||||
}
|
|
||||||
val network = requireNotNull(
|
val network = requireNotNull(
|
||||||
networkFactory.create(
|
networkFactory.create(
|
||||||
networkId = networkId,
|
networkId = networkId,
|
||||||
|
|
@ -189,9 +186,7 @@ internal class DefaultCustomTokensRepository(
|
||||||
derivationPath: Network.DerivationPath,
|
derivationPath: Network.DerivationPath,
|
||||||
formValues: AddCustomTokenForm.Validated.All,
|
formValues: AddCustomTokenForm.Validated.All,
|
||||||
): CryptoCurrency.Token {
|
): CryptoCurrency.Token {
|
||||||
val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
|
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||||
"User wallet [$userWalletId] not found while creating custom token"
|
|
||||||
}
|
|
||||||
val network = requireNotNull(
|
val network = requireNotNull(
|
||||||
networkFactory.create(
|
networkFactory.create(
|
||||||
networkId = networkId,
|
networkId = networkId,
|
||||||
|
|
@ -217,6 +212,7 @@ internal class DefaultCustomTokensRepository(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||||
override suspend fun removeCurrency(userWalletId: UserWalletId, currency: ManagedCryptoCurrency.Custom) =
|
override suspend fun removeCurrency(userWalletId: UserWalletId, currency: ManagedCryptoCurrency.Custom) =
|
||||||
withContext(dispatchers.io) {
|
withContext(dispatchers.io) {
|
||||||
val cryptoCurrency = when (currency) {
|
val cryptoCurrency = when (currency) {
|
||||||
|
|
@ -273,20 +269,15 @@ internal class DefaultCustomTokensRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getSupportedNetworks(userWalletId: UserWalletId): List<Network> = withContext(dispatchers.io) {
|
override suspend fun getSupportedNetworks(userWalletId: UserWalletId): List<Network> = withContext(dispatchers.io) {
|
||||||
val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
|
when (val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)) {
|
||||||
"User wallet [$userWalletId] not found while getting supported networks"
|
|
||||||
}
|
|
||||||
|
|
||||||
when (userWallet) {
|
|
||||||
is UserWallet.Hot -> {
|
is UserWallet.Hot -> {
|
||||||
Blockchain.entries.mapNotNull {
|
Blockchain.entries.mapNotNull { blockchain ->
|
||||||
// TODO: refactor [REDACTED_JIRA]\
|
// TODO: refactor [REDACTED_JIRA]
|
||||||
if (it.isTestnet() || it in excludedBlockchains || it in hotWalletExcludedBlockchains) {
|
val isExcluded = blockchain in excludedBlockchains || blockchain in hotWalletExcludedBlockchains
|
||||||
return@mapNotNull null
|
if (blockchain.isTestnet() || isExcluded) return@mapNotNull null
|
||||||
}
|
|
||||||
|
|
||||||
networkFactory.create(
|
networkFactory.create(
|
||||||
blockchain = it,
|
blockchain = blockchain,
|
||||||
extraDerivationPath = null,
|
extraDerivationPath = null,
|
||||||
userWallet = userWallet,
|
userWallet = userWallet,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@ import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||||
import com.tangem.datasource.api.tangemTech.models.orDefault
|
import com.tangem.datasource.api.tangemTech.models.orDefault
|
||||||
import com.tangem.datasource.local.config.testnet.TestnetTokensStorage
|
import com.tangem.datasource.local.config.testnet.TestnetTokensStorage
|
||||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
|
||||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||||
import com.tangem.domain.card.common.TapWorkarounds.isTestCard
|
import com.tangem.domain.card.common.TapWorkarounds.isTestCard
|
||||||
import com.tangem.domain.card.common.extensions.*
|
import com.tangem.domain.card.common.extensions.*
|
||||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||||
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
import com.tangem.domain.managetokens.model.*
|
import com.tangem.domain.managetokens.model.*
|
||||||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency.SourceNetwork
|
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency.SourceNetwork
|
||||||
import com.tangem.domain.managetokens.repository.ManageTokensRepository
|
import com.tangem.domain.managetokens.repository.ManageTokensRepository
|
||||||
|
|
@ -46,7 +46,7 @@ import com.tangem.utils.coroutines.runSuspendCatching
|
||||||
@Suppress("LongParameterList", "LargeClass")
|
@Suppress("LongParameterList", "LargeClass")
|
||||||
internal class DefaultManageTokensRepository(
|
internal class DefaultManageTokensRepository(
|
||||||
private val tangemTechApi: TangemTechApi,
|
private val tangemTechApi: TangemTechApi,
|
||||||
private val userWalletsStore: UserWalletsStore,
|
private val userWalletsListRepository: UserWalletsListRepository,
|
||||||
private val userTokenSaver: UserTokensSaver,
|
private val userTokenSaver: UserTokensSaver,
|
||||||
private val manageTokensUpdateFetcher: ManageTokensUpdateFetcher,
|
private val manageTokensUpdateFetcher: ManageTokensUpdateFetcher,
|
||||||
private val userTokensResponseStore: UserTokensResponseStore,
|
private val userTokensResponseStore: UserTokensResponseStore,
|
||||||
|
|
@ -88,7 +88,7 @@ internal class DefaultManageTokensRepository(
|
||||||
prefetchDistance = batchSize,
|
prefetchDistance = batchSize,
|
||||||
batchSize = batchSize,
|
batchSize = batchSize,
|
||||||
subFetcher = { request, _, isFirstBatchFetching ->
|
subFetcher = { request, _, isFirstBatchFetching ->
|
||||||
val userWallet = request.params.userWalletId?.let(userWalletsStore::getSyncStrict)
|
val userWallet = request.params.userWalletId?.let(userWalletsListRepository::getSyncStrict)
|
||||||
|
|
||||||
if (userWallet is UserWallet.Cold && userWallet.scanResponse.card.isTestCard) {
|
if (userWallet is UserWallet.Cold && userWallet.scanResponse.card.isTestCard) {
|
||||||
when (val params = request.params) {
|
when (val params = request.params) {
|
||||||
|
|
@ -438,7 +438,7 @@ internal class DefaultManageTokensRepository(
|
||||||
userWalletId: UserWalletId,
|
userWalletId: UserWalletId,
|
||||||
sourceNetwork: SourceNetwork,
|
sourceNetwork: SourceNetwork,
|
||||||
): CurrencyUnsupportedState? {
|
): CurrencyUnsupportedState? {
|
||||||
val userWallet = userWalletsStore.getSyncStrict(key = userWalletId)
|
val userWallet = userWalletsListRepository.getSyncStrict(id = userWalletId)
|
||||||
val blockchain = sourceNetwork.id.toBlockchain()
|
val blockchain = sourceNetwork.id.toBlockchain()
|
||||||
|
|
||||||
return when (sourceNetwork) {
|
return when (sourceNetwork) {
|
||||||
|
|
@ -452,7 +452,7 @@ internal class DefaultManageTokensRepository(
|
||||||
rawNetworkId: String,
|
rawNetworkId: String,
|
||||||
isMainNetwork: Boolean,
|
isMainNetwork: Boolean,
|
||||||
): CurrencyUnsupportedState? {
|
): CurrencyUnsupportedState? {
|
||||||
val userWallet = userWalletsStore.getSyncStrict(key = userWalletId)
|
val userWallet = userWalletsListRepository.getSyncStrict(id = userWalletId)
|
||||||
val blockchain = Blockchain.fromNetworkId(networkId = rawNetworkId)
|
val blockchain = Blockchain.fromNetworkId(networkId = rawNetworkId)
|
||||||
?: error("Can not create blockchain with given networkId -> $rawNetworkId")
|
?: error("Can not create blockchain with given networkId -> $rawNetworkId")
|
||||||
return if (isMainNetwork) {
|
return if (isMainNetwork) {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ import com.tangem.data.managetokens.utils.ManageTokensUpdateFetcher
|
||||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||||
import com.tangem.datasource.local.config.testnet.TestnetTokensStorage
|
import com.tangem.datasource.local.config.testnet.TestnetTokensStorage
|
||||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
|
||||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||||
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
import com.tangem.domain.managetokens.repository.CustomTokensRepository
|
import com.tangem.domain.managetokens.repository.CustomTokensRepository
|
||||||
import com.tangem.domain.managetokens.repository.ManageTokensRepository
|
import com.tangem.domain.managetokens.repository.ManageTokensRepository
|
||||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||||
|
|
@ -31,7 +31,7 @@ internal object ManageTokensDataModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideManageTokensRepository(
|
fun provideManageTokensRepository(
|
||||||
tangemTechApi: TangemTechApi,
|
tangemTechApi: TangemTechApi,
|
||||||
userWalletsStore: UserWalletsStore,
|
userWalletsListRepository: UserWalletsListRepository,
|
||||||
manageTokensUpdateFetcher: ManageTokensUpdateFetcher,
|
manageTokensUpdateFetcher: ManageTokensUpdateFetcher,
|
||||||
userTokensResponseStore: UserTokensResponseStore,
|
userTokensResponseStore: UserTokensResponseStore,
|
||||||
userTokensSaver: UserTokensSaver,
|
userTokensSaver: UserTokensSaver,
|
||||||
|
|
@ -45,7 +45,7 @@ internal object ManageTokensDataModule {
|
||||||
): ManageTokensRepository {
|
): ManageTokensRepository {
|
||||||
return DefaultManageTokensRepository(
|
return DefaultManageTokensRepository(
|
||||||
tangemTechApi = tangemTechApi,
|
tangemTechApi = tangemTechApi,
|
||||||
userWalletsStore = userWalletsStore,
|
userWalletsListRepository = userWalletsListRepository,
|
||||||
manageTokensUpdateFetcher = manageTokensUpdateFetcher,
|
manageTokensUpdateFetcher = manageTokensUpdateFetcher,
|
||||||
userTokensResponseStore = userTokensResponseStore,
|
userTokensResponseStore = userTokensResponseStore,
|
||||||
userTokenSaver = userTokensSaver,
|
userTokenSaver = userTokensSaver,
|
||||||
|
|
@ -63,7 +63,7 @@ internal object ManageTokensDataModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideCustomTokensRepository(
|
fun provideCustomTokensRepository(
|
||||||
tangemTechApi: TangemTechApi,
|
tangemTechApi: TangemTechApi,
|
||||||
userWalletsStore: UserWalletsStore,
|
userWalletsListRepository: UserWalletsListRepository,
|
||||||
userTokensResponseStore: UserTokensResponseStore,
|
userTokensResponseStore: UserTokensResponseStore,
|
||||||
walletManagersFacade: WalletManagersFacade,
|
walletManagersFacade: WalletManagersFacade,
|
||||||
dispatchers: CoroutineDispatcherProvider,
|
dispatchers: CoroutineDispatcherProvider,
|
||||||
|
|
@ -73,7 +73,7 @@ internal object ManageTokensDataModule {
|
||||||
): CustomTokensRepository {
|
): CustomTokensRepository {
|
||||||
return DefaultCustomTokensRepository(
|
return DefaultCustomTokensRepository(
|
||||||
tangemTechApi = tangemTechApi,
|
tangemTechApi = tangemTechApi,
|
||||||
userWalletsStore = userWalletsStore,
|
userWalletsListRepository = userWalletsListRepository,
|
||||||
userTokensResponseStore = userTokensResponseStore,
|
userTokensResponseStore = userTokensResponseStore,
|
||||||
walletManagersFacade = walletManagersFacade,
|
walletManagersFacade = walletManagersFacade,
|
||||||
excludedBlockchains = excludedBlockchains,
|
excludedBlockchains = excludedBlockchains,
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,9 @@ internal class ManageTokensUpdateFetcher @Inject constructor() :
|
||||||
|
|
||||||
update {
|
update {
|
||||||
BatchUpdateResult.Success(
|
BatchUpdateResult.Success(
|
||||||
data = mapNotNull {
|
data = mapNotNull { batch ->
|
||||||
if (it.key == toUpdate[index].key) {
|
if (batch.key == toUpdate[index].key) {
|
||||||
Batch(it.key, updatedItems)
|
Batch(batch.key, updatedItems)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ import com.tangem.data.visa.config.VisaLibLoader
|
||||||
import com.tangem.data.visa.utils.*
|
import com.tangem.data.visa.utils.*
|
||||||
import com.tangem.datasource.api.visa.VisaApi
|
import com.tangem.datasource.api.visa.VisaApi
|
||||||
import com.tangem.datasource.api.visa.models.response.VisaTxHistoryResponse
|
import com.tangem.datasource.api.visa.models.response.VisaTxHistoryResponse
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
|
||||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||||
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.domain.models.wallet.requireColdWallet
|
import com.tangem.domain.models.wallet.requireColdWallet
|
||||||
|
|
@ -40,7 +40,7 @@ internal class DefaultVisaRepository @Inject constructor(
|
||||||
private val visaLibLoader: VisaLibLoader,
|
private val visaLibLoader: VisaLibLoader,
|
||||||
private val quotesFetcher: QuotesFetcher,
|
private val quotesFetcher: QuotesFetcher,
|
||||||
private val cacheRegistry: CacheRegistry,
|
private val cacheRegistry: CacheRegistry,
|
||||||
private val userWalletsStore: UserWalletsStore,
|
private val userWalletsListRepository: UserWalletsListRepository,
|
||||||
private val dispatchers: CoroutineDispatcherProvider,
|
private val dispatchers: CoroutineDispatcherProvider,
|
||||||
private val visaApiRequestMaker: VisaApiRequestMaker,
|
private val visaApiRequestMaker: VisaApiRequestMaker,
|
||||||
private val visaApi: VisaApi,
|
private val visaApi: VisaApi,
|
||||||
|
|
@ -176,7 +176,7 @@ internal class DefaultVisaRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun makeAddress(userWalletId: UserWalletId): String {
|
private fun makeAddress(userWalletId: UserWalletId): String {
|
||||||
if (VisaConstants.IS_DEMO_MODE_ENABLED) return getDemoAddress()
|
if (VisaConstants.IS_DEMO_MODE_ENABLED) return getDemoAddress()
|
||||||
|
|
||||||
val userWallet = findVisaUserWallet(userWalletId)
|
val userWallet = findVisaUserWallet(userWalletId)
|
||||||
|
|
@ -219,9 +219,7 @@ internal class DefaultVisaRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findVisaUserWallet(userWalletId: UserWalletId): UserWallet {
|
private fun findVisaUserWallet(userWalletId: UserWalletId): UserWallet {
|
||||||
val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
|
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||||
"No user wallet found: $userWalletId"
|
|
||||||
}
|
|
||||||
if (!userWallet.requireColdWallet().scanResponse.cardTypesResolver.isVisaWallet()) {
|
if (!userWallet.requireColdWallet().scanResponse.cardTypesResolver.isVisaWallet()) {
|
||||||
error("VISA wallet required: $userWalletId")
|
error("VISA wallet required: $userWalletId")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ import com.tangem.datasource.api.common.response.ApiResponseError
|
||||||
import com.tangem.datasource.api.common.response.getOrThrow
|
import com.tangem.datasource.api.common.response.getOrThrow
|
||||||
import com.tangem.datasource.api.pay.models.request.RefreshTokenByCardWalletRequest
|
import com.tangem.datasource.api.pay.models.request.RefreshTokenByCardWalletRequest
|
||||||
import com.tangem.datasource.api.visa.VisaApi
|
import com.tangem.datasource.api.visa.VisaApi
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
|
||||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||||
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
|
import com.tangem.domain.common.wallets.update
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.domain.models.wallet.requireColdWallet
|
import com.tangem.domain.models.wallet.requireColdWallet
|
||||||
|
|
@ -23,7 +24,7 @@ import javax.inject.Inject
|
||||||
typealias VisaAuthorizationHeader = String
|
typealias VisaAuthorizationHeader = String
|
||||||
|
|
||||||
internal class VisaApiRequestMaker @Inject constructor(
|
internal class VisaApiRequestMaker @Inject constructor(
|
||||||
private val userWalletsStore: UserWalletsStore,
|
private val userWalletsListRepository: UserWalletsListRepository,
|
||||||
private val visaAuthApi: VisaApi,
|
private val visaAuthApi: VisaApi,
|
||||||
private val accessCodeDataConverter: AccessCodeDataConverter,
|
private val accessCodeDataConverter: AccessCodeDataConverter,
|
||||||
private val dispatcherProvider: CoroutineDispatcherProvider,
|
private val dispatcherProvider: CoroutineDispatcherProvider,
|
||||||
|
|
@ -47,11 +48,11 @@ internal class VisaApiRequestMaker @Inject constructor(
|
||||||
|
|
||||||
val newTokens = runCatching {
|
val newTokens = runCatching {
|
||||||
refreshAccessTokens(authTokens.refreshToken)
|
refreshAccessTokens(authTokens.refreshToken)
|
||||||
}.getOrElse {
|
}.getOrElse { throwable ->
|
||||||
if (it is ApiResponseError.HttpException &&
|
if (throwable is ApiResponseError.HttpException &&
|
||||||
it.code == ApiResponseError.HttpException.Code.UNAUTHORIZED
|
throwable.code == ApiResponseError.HttpException.Code.UNAUTHORIZED
|
||||||
) {
|
) {
|
||||||
userWalletsStore.update(userWalletId) { userWallet ->
|
userWalletsListRepository.update(userWalletId) { userWallet ->
|
||||||
userWallet.requireColdWallet().copy(
|
userWallet.requireColdWallet().copy(
|
||||||
scanResponse = userWallet.scanResponse.copy(
|
scanResponse = userWallet.scanResponse.copy(
|
||||||
// visaCardActivationStatus = VisaCardActivationStatus.RefreshTokenExpired,
|
// visaCardActivationStatus = VisaCardActivationStatus.RefreshTokenExpired,
|
||||||
|
|
@ -62,7 +63,7 @@ internal class VisaApiRequestMaker @Inject constructor(
|
||||||
throw RefreshTokenExpiredException()
|
throw RefreshTokenExpiredException()
|
||||||
}
|
}
|
||||||
|
|
||||||
userWalletsStore.update(userWalletId) { userWallet ->
|
userWalletsListRepository.update(userWalletId) { userWallet ->
|
||||||
userWallet.requireColdWallet().copy(
|
userWallet.requireColdWallet().copy(
|
||||||
scanResponse = userWallet.scanResponse.copy(
|
scanResponse = userWallet.scanResponse.copy(
|
||||||
// visaCardActivationStatus = VisaCardActivationStatus.Activated(
|
// visaCardActivationStatus = VisaCardActivationStatus.Activated(
|
||||||
|
|
@ -92,7 +93,7 @@ internal class VisaApiRequestMaker @Inject constructor(
|
||||||
|
|
||||||
@Throws
|
@Throws
|
||||||
private fun getAuthTokens(userWalletId: UserWalletId): VisaAuthTokens {
|
private fun getAuthTokens(userWalletId: UserWalletId): VisaAuthTokens {
|
||||||
val userWallet = findVisaUserWallet(userWalletId)
|
findVisaUserWallet(userWalletId)
|
||||||
// val status = userWallet.requireColdWallet().scanResponse.visaCardActivationStatus
|
// val status = userWallet.requireColdWallet().scanResponse.visaCardActivationStatus
|
||||||
// ?: error("Visa card activation status not found")
|
// ?: error("Visa card activation status not found")
|
||||||
val status: VisaCardActivationStatus = TODO("Fix visaCardActivationStatus retrieval")
|
val status: VisaCardActivationStatus = TODO("Fix visaCardActivationStatus retrieval")
|
||||||
|
|
@ -105,9 +106,7 @@ internal class VisaApiRequestMaker @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findVisaUserWallet(userWalletId: UserWalletId): UserWallet {
|
private fun findVisaUserWallet(userWalletId: UserWalletId): UserWallet {
|
||||||
val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
|
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||||
"No user wallet found: $userWalletId"
|
|
||||||
}
|
|
||||||
if (!userWallet.requireColdWallet().scanResponse.cardTypesResolver.isVisaWallet()) {
|
if (!userWallet.requireColdWallet().scanResponse.cardTypesResolver.isVisaWallet()) {
|
||||||
error("VISA wallet required: $userWalletId")
|
error("VISA wallet required: $userWalletId")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,10 @@ android {
|
||||||
namespace = "com.tangem.data.wallet"
|
namespace = "com.tangem.data.wallet"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType<Test>().configureEach {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(projects.data.common)
|
implementation(projects.data.common)
|
||||||
|
|
||||||
|
|
@ -47,9 +51,7 @@ dependencies {
|
||||||
implementation(deps.timber)
|
implementation(deps.timber)
|
||||||
|
|
||||||
/** tests */
|
/** tests */
|
||||||
|
testImplementation(projects.test.core)
|
||||||
testImplementation(projects.common.test)
|
testImplementation(projects.common.test)
|
||||||
testImplementation(deps.test.junit)
|
testRuntimeOnly(deps.test.junit5.engine)
|
||||||
testImplementation(deps.test.coroutine)
|
|
||||||
testImplementation(deps.test.truth)
|
|
||||||
testImplementation(deps.test.mockk)
|
|
||||||
}
|
}
|
||||||
|
|
@ -9,7 +9,7 @@ import com.tangem.datasource.api.tangemTech.models.BindWalletsByReferralCodeBody
|
||||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||||
import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull
|
import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull
|
||||||
import com.tangem.datasource.local.preferences.utils.storeObject
|
import com.tangem.datasource.local.preferences.utils.storeObject
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
import com.tangem.domain.wallets.models.AppsFlyerConversionData
|
import com.tangem.domain.wallets.models.AppsFlyerConversionData
|
||||||
import com.tangem.domain.wallets.repository.WalletsPromoRepository
|
import com.tangem.domain.wallets.repository.WalletsPromoRepository
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
|
|
@ -19,7 +19,7 @@ import timber.log.Timber
|
||||||
internal class DefaultWalletsPromoRepository(
|
internal class DefaultWalletsPromoRepository(
|
||||||
private val appPreferencesStore: AppPreferencesStore,
|
private val appPreferencesStore: AppPreferencesStore,
|
||||||
private val tangemTechApi: TangemTechApi,
|
private val tangemTechApi: TangemTechApi,
|
||||||
private val userWalletsStore: UserWalletsStore,
|
private val userWalletsListRepository: UserWalletsListRepository,
|
||||||
private val dispatchers: CoroutineDispatcherProvider,
|
private val dispatchers: CoroutineDispatcherProvider,
|
||||||
) : WalletsPromoRepository {
|
) : WalletsPromoRepository {
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ internal class DefaultWalletsPromoRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun bind(refcode: String, campaign: String?) {
|
private suspend fun bind(refcode: String, campaign: String?) {
|
||||||
val walletIds = userWalletsStore.userWalletsSync.map { it.walletId.stringValue }
|
val walletIds = userWalletsListRepository.userWallets.value.orEmpty().map { it.walletId.stringValue }
|
||||||
|
|
||||||
val result = tangemTechApi.bindWalletsByReferralCode(
|
val result = tangemTechApi.bindWalletsByReferralCode(
|
||||||
body = BindWalletsByReferralCodeBody(walletIds = walletIds, refcode = refcode, campaign = campaign),
|
body = BindWalletsByReferralCodeBody(walletIds = walletIds, refcode = refcode, campaign = campaign),
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ import com.tangem.datasource.local.preferences.utils.getObjectMap
|
||||||
import com.tangem.datasource.local.preferences.utils.getSyncOrDefault
|
import com.tangem.datasource.local.preferences.utils.getSyncOrDefault
|
||||||
import com.tangem.datasource.local.preferences.utils.getSyncOrNull
|
import com.tangem.datasource.local.preferences.utils.getSyncOrNull
|
||||||
import com.tangem.datasource.local.preferences.utils.store
|
import com.tangem.datasource.local.preferences.utils.store
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
|
||||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||||
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.domain.wallets.models.SeedPhraseNotificationsStatus
|
import com.tangem.domain.wallets.models.SeedPhraseNotificationsStatus
|
||||||
|
|
@ -47,7 +47,7 @@ typealias SeedPhraseNotificationsStatuses = Map<UserWalletId, SeedPhraseNotifica
|
||||||
internal class DefaultWalletsRepository(
|
internal class DefaultWalletsRepository(
|
||||||
private val appPreferencesStore: AppPreferencesStore,
|
private val appPreferencesStore: AppPreferencesStore,
|
||||||
private val tangemTechApi: TangemTechApi,
|
private val tangemTechApi: TangemTechApi,
|
||||||
private val userWalletsStore: UserWalletsStore,
|
private val userWalletsListRepository: UserWalletsListRepository,
|
||||||
private val seedPhraseNotificationVisibilityStore: RuntimeStateStore<SeedPhraseNotificationsStatuses>,
|
private val seedPhraseNotificationVisibilityStore: RuntimeStateStore<SeedPhraseNotificationsStatuses>,
|
||||||
private val dispatchers: CoroutineDispatcherProvider,
|
private val dispatchers: CoroutineDispatcherProvider,
|
||||||
private val authProvider: AuthProvider,
|
private val authProvider: AuthProvider,
|
||||||
|
|
@ -151,7 +151,7 @@ internal class DefaultWalletsRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun fetchSeedPhraseNotificationStatus(userWalletId: UserWalletId) {
|
private suspend fun fetchSeedPhraseNotificationStatus(userWalletId: UserWalletId) {
|
||||||
val userWallet = userWalletsStore.getSyncOrNull(key = userWalletId)
|
val userWallet = userWalletsListRepository.getSyncOrNull(id = userWalletId)
|
||||||
|
|
||||||
if (userWallet != null && userWallet !is UserWallet.Cold) {
|
if (userWallet != null && userWallet !is UserWallet.Cold) {
|
||||||
updateNotificationVisibility(id = userWalletId, value = SeedPhraseNotificationsStatus.NOT_NEEDED)
|
updateNotificationVisibility(id = userWalletId, value = SeedPhraseNotificationsStatus.NOT_NEEDED)
|
||||||
|
|
@ -323,7 +323,7 @@ internal class DefaultWalletsRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun setWalletName(walletId: UserWalletId, walletName: String) = withContext(dispatchers.io) {
|
override suspend fun setWalletName(walletId: UserWalletId, walletName: String) = withContext(dispatchers.io) {
|
||||||
val userWallet = userWalletsStore.getSyncOrNull(key = walletId)
|
val userWallet = userWalletsListRepository.getSyncOrNull(id = walletId)
|
||||||
|
|
||||||
tangemTechApi.updateWallet(
|
tangemTechApi.updateWallet(
|
||||||
walletId = walletId.stringValue,
|
walletId = walletId.stringValue,
|
||||||
|
|
@ -332,7 +332,7 @@ internal class DefaultWalletsRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun upgradeWallet(walletId: UserWalletId) = withContext(dispatchers.io) {
|
override suspend fun upgradeWallet(walletId: UserWalletId) = withContext(dispatchers.io) {
|
||||||
val userWallet = userWalletsStore.getSyncStrict(key = walletId)
|
val userWallet = userWalletsListRepository.getSyncStrict(id = walletId)
|
||||||
|
|
||||||
tangemTechApi.updateWallet(
|
tangemTechApi.updateWallet(
|
||||||
walletId = walletId.stringValue,
|
walletId = walletId.stringValue,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package com.tangem.data.wallets.derivations
|
package com.tangem.data.wallets.derivations
|
||||||
|
|
||||||
import com.tangem.common.CompletionResult
|
import arrow.core.getOrElse
|
||||||
import com.tangem.common.extensions.ByteArrayKey
|
import com.tangem.common.extensions.ByteArrayKey
|
||||||
import com.tangem.crypto.hdWallet.DerivationPath
|
import com.tangem.crypto.hdWallet.DerivationPath
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
import com.tangem.domain.models.account.DerivationIndex
|
import com.tangem.domain.models.account.DerivationIndex
|
||||||
import com.tangem.domain.models.currency.CryptoCurrency
|
import com.tangem.domain.models.currency.CryptoCurrency
|
||||||
import com.tangem.domain.models.network.Network
|
import com.tangem.domain.models.network.Network
|
||||||
|
|
@ -16,16 +16,22 @@ import com.tangem.domain.wallets.usecase.BackendId
|
||||||
import com.tangem.operations.derivation.ExtendedPublicKeysMap
|
import com.tangem.operations.derivation.ExtendedPublicKeysMap
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultDerivationsRepository @Inject constructor(
|
internal class DefaultDerivationsRepository @Inject constructor(
|
||||||
private val userWalletsStore: UserWalletsStore,
|
private val userWalletsListRepository: UserWalletsListRepository,
|
||||||
private val hotDerivationsRepository: HotMapDerivationsRepository,
|
private val hotDerivationsRepository: HotMapDerivationsRepository,
|
||||||
private val coldDerivationsRepository: ColdMapDerivationsRepository,
|
private val coldDerivationsRepository: ColdMapDerivationsRepository,
|
||||||
private val dispatchers: CoroutineDispatcherProvider,
|
private val dispatchers: CoroutineDispatcherProvider,
|
||||||
) : DerivationsRepository {
|
) : DerivationsRepository {
|
||||||
|
|
||||||
override suspend fun derivePublicKeys(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
override suspend fun derivePublicKeys(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
||||||
|
if (currencies.isEmpty()) {
|
||||||
|
Timber.d("Nothing to derive")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
derivePublicKeysByNetworks(userWalletId = userWalletId, networks = currencies.map(CryptoCurrency::network))
|
derivePublicKeysByNetworks(userWalletId = userWalletId, networks = currencies.map(CryptoCurrency::network))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,7 +40,7 @@ internal class DefaultDerivationsRepository @Inject constructor(
|
||||||
networkIds: List<Network.RawID>,
|
networkIds: List<Network.RawID>,
|
||||||
accountIndex: DerivationIndex,
|
accountIndex: DerivationIndex,
|
||||||
) {
|
) {
|
||||||
val userWallet = userWalletsStore.getSyncStrict(userWalletId)
|
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||||
when (userWallet) {
|
when (userWallet) {
|
||||||
is UserWallet.Cold -> coldDerivationsRepository.derivePublicKeysByNetworkIds(userWallet, networkIds)
|
is UserWallet.Cold -> coldDerivationsRepository.derivePublicKeysByNetworkIds(userWallet, networkIds)
|
||||||
is UserWallet.Hot -> {
|
is UserWallet.Hot -> {
|
||||||
|
|
@ -46,7 +52,7 @@ internal class DefaultDerivationsRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun derivePublicKeysByNetworks(userWalletId: UserWalletId, networks: List<Network>) {
|
override suspend fun derivePublicKeysByNetworks(userWalletId: UserWalletId, networks: List<Network>) {
|
||||||
val userWallet = userWalletsStore.getSyncStrict(userWalletId)
|
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||||
when (userWallet) {
|
when (userWallet) {
|
||||||
is UserWallet.Cold -> coldDerivationsRepository.derivePublicKeysByNetworks(userWallet, networks)
|
is UserWallet.Cold -> coldDerivationsRepository.derivePublicKeysByNetworks(userWallet, networks)
|
||||||
is UserWallet.Hot -> hotDerivationsRepository.derivePublicKeysByNetworks(userWallet, networks)
|
is UserWallet.Hot -> hotDerivationsRepository.derivePublicKeysByNetworks(userWallet, networks)
|
||||||
|
|
@ -59,7 +65,7 @@ internal class DefaultDerivationsRepository @Inject constructor(
|
||||||
userWalletId: UserWalletId,
|
userWalletId: UserWalletId,
|
||||||
derivations: Map<ByteArrayKey, List<DerivationPath>>,
|
derivations: Map<ByteArrayKey, List<DerivationPath>>,
|
||||||
): Map<ByteArrayKey, ExtendedPublicKeysMap> {
|
): Map<ByteArrayKey, ExtendedPublicKeysMap> {
|
||||||
val userWallet = userWalletsStore.getSyncStrict(userWalletId)
|
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||||
return when (userWallet) {
|
return when (userWallet) {
|
||||||
is UserWallet.Cold -> coldDerivationsRepository.derivePublicKeys(userWallet, derivations)
|
is UserWallet.Cold -> coldDerivationsRepository.derivePublicKeys(userWallet, derivations)
|
||||||
is UserWallet.Hot -> hotDerivationsRepository.derivePublicKeys(userWallet, derivations)
|
is UserWallet.Hot -> hotDerivationsRepository.derivePublicKeys(userWallet, derivations)
|
||||||
|
|
@ -73,7 +79,7 @@ internal class DefaultDerivationsRepository @Inject constructor(
|
||||||
userWalletId: UserWalletId,
|
userWalletId: UserWalletId,
|
||||||
networksWithDerivationPath: Map<BackendId, String?>,
|
networksWithDerivationPath: Map<BackendId, String?>,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return when (val userWallet = userWalletsStore.getSyncStrict(userWalletId)) {
|
return when (val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)) {
|
||||||
is UserWallet.Cold -> coldDerivationsRepository.hasMissedDerivations(userWallet, networksWithDerivationPath)
|
is UserWallet.Cold -> coldDerivationsRepository.hasMissedDerivations(userWallet, networksWithDerivationPath)
|
||||||
is UserWallet.Hot -> hotDerivationsRepository.hasMissedDerivations(userWallet, networksWithDerivationPath)
|
is UserWallet.Hot -> hotDerivationsRepository.hasMissedDerivations(userWallet, networksWithDerivationPath)
|
||||||
}
|
}
|
||||||
|
|
@ -88,14 +94,7 @@ internal class DefaultDerivationsRepository @Inject constructor(
|
||||||
return@withContext // No update needed
|
return@withContext // No update needed
|
||||||
}
|
}
|
||||||
|
|
||||||
val updateResult = userWalletsStore.update(
|
userWalletsListRepository.saveWithoutLock(userWallet = newUserWallet, canOverride = true)
|
||||||
userWalletId = newUserWallet.walletId,
|
.getOrElse { throw IllegalStateException("Unable to update user wallet: $it") }
|
||||||
update = { userWalletToUpdate -> newUserWallet },
|
|
||||||
)
|
|
||||||
|
|
||||||
when (updateResult) {
|
|
||||||
is CompletionResult.Failure -> throw updateResult.error
|
|
||||||
is CompletionResult.Success -> updateResult.data
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -15,8 +15,8 @@ import com.tangem.datasource.di.NetworkMoshi
|
||||||
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
|
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
|
||||||
import com.tangem.datasource.local.datastore.RuntimeStateStore
|
import com.tangem.datasource.local.datastore.RuntimeStateStore
|
||||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
|
||||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||||
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
import com.tangem.domain.wallets.derivations.ColdMapDerivationsRepository
|
import com.tangem.domain.wallets.derivations.ColdMapDerivationsRepository
|
||||||
import com.tangem.domain.wallets.derivations.DerivationsRepository
|
import com.tangem.domain.wallets.derivations.DerivationsRepository
|
||||||
import com.tangem.domain.wallets.derivations.HotMapDerivationsRepository
|
import com.tangem.domain.wallets.derivations.HotMapDerivationsRepository
|
||||||
|
|
@ -41,7 +41,7 @@ internal object WalletsDataModule {
|
||||||
fun providesWalletsRepository(
|
fun providesWalletsRepository(
|
||||||
appPreferencesStore: AppPreferencesStore,
|
appPreferencesStore: AppPreferencesStore,
|
||||||
tangemTechApi: TangemTechApi,
|
tangemTechApi: TangemTechApi,
|
||||||
userWalletsStore: UserWalletsStore,
|
userWalletsListRepository: UserWalletsListRepository,
|
||||||
dispatchers: CoroutineDispatcherProvider,
|
dispatchers: CoroutineDispatcherProvider,
|
||||||
authProvider: AuthProvider,
|
authProvider: AuthProvider,
|
||||||
walletServerBinder: WalletServerBinder,
|
walletServerBinder: WalletServerBinder,
|
||||||
|
|
@ -52,7 +52,7 @@ internal object WalletsDataModule {
|
||||||
return DefaultWalletsRepository(
|
return DefaultWalletsRepository(
|
||||||
appPreferencesStore = appPreferencesStore,
|
appPreferencesStore = appPreferencesStore,
|
||||||
tangemTechApi = tangemTechApi,
|
tangemTechApi = tangemTechApi,
|
||||||
userWalletsStore = userWalletsStore,
|
userWalletsListRepository = userWalletsListRepository,
|
||||||
seedPhraseNotificationVisibilityStore = RuntimeStateStore(defaultValue = emptyMap()),
|
seedPhraseNotificationVisibilityStore = RuntimeStateStore(defaultValue = emptyMap()),
|
||||||
dispatchers = dispatchers,
|
dispatchers = dispatchers,
|
||||||
authProvider = authProvider,
|
authProvider = authProvider,
|
||||||
|
|
@ -74,13 +74,13 @@ internal object WalletsDataModule {
|
||||||
fun provideWalletsPromoRepository(
|
fun provideWalletsPromoRepository(
|
||||||
appPreferencesStore: AppPreferencesStore,
|
appPreferencesStore: AppPreferencesStore,
|
||||||
tangemTechApi: TangemTechApi,
|
tangemTechApi: TangemTechApi,
|
||||||
userWalletsStore: UserWalletsStore,
|
userWalletsListRepository: UserWalletsListRepository,
|
||||||
dispatchers: CoroutineDispatcherProvider,
|
dispatchers: CoroutineDispatcherProvider,
|
||||||
): WalletsPromoRepository {
|
): WalletsPromoRepository {
|
||||||
return DefaultWalletsPromoRepository(
|
return DefaultWalletsPromoRepository(
|
||||||
appPreferencesStore = appPreferencesStore,
|
appPreferencesStore = appPreferencesStore,
|
||||||
tangemTechApi = tangemTechApi,
|
tangemTechApi = tangemTechApi,
|
||||||
userWalletsStore = userWalletsStore,
|
userWalletsListRepository = userWalletsListRepository,
|
||||||
dispatchers = dispatchers,
|
dispatchers = dispatchers,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import com.tangem.common.extensions.toMapKey
|
||||||
import com.tangem.crypto.hdWallet.DerivationPath
|
import com.tangem.crypto.hdWallet.DerivationPath
|
||||||
import com.tangem.data.common.network.NetworkFactory
|
import com.tangem.data.common.network.NetworkFactory
|
||||||
import com.tangem.data.wallets.derivations.MissedDerivationsFinder
|
import com.tangem.data.wallets.derivations.MissedDerivationsFinder
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
import com.tangem.domain.models.account.DerivationIndex
|
import com.tangem.domain.models.account.DerivationIndex
|
||||||
import com.tangem.domain.models.currency.CryptoCurrency
|
import com.tangem.domain.models.currency.CryptoCurrency
|
||||||
import com.tangem.domain.models.network.Network
|
import com.tangem.domain.models.network.Network
|
||||||
|
|
@ -23,7 +23,7 @@ import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultHotMapDerivationsRepository @Inject constructor(
|
internal class DefaultHotMapDerivationsRepository @Inject constructor(
|
||||||
private val userWalletsStore: UserWalletsStore,
|
private val userWalletsListRepository: UserWalletsListRepository,
|
||||||
private val networkFactory: NetworkFactory,
|
private val networkFactory: NetworkFactory,
|
||||||
private val hotWalletAccessor: HotWalletAccessor,
|
private val hotWalletAccessor: HotWalletAccessor,
|
||||||
private val dispatchers: CoroutineDispatcherProvider,
|
private val dispatchers: CoroutineDispatcherProvider,
|
||||||
|
|
@ -90,7 +90,7 @@ internal class DefaultHotMapDerivationsRepository @Inject constructor(
|
||||||
|
|
||||||
// Get the updated user wallet from the store to ensure we have the latest data
|
// Get the updated user wallet from the store to ensure we have the latest data
|
||||||
// in case it was modified during the derive operation
|
// in case it was modified during the derive operation
|
||||||
val updatedUserWallet = userWalletsStore.getSyncStrict(userWallet.walletId) as UserWallet.Hot
|
val updatedUserWallet = userWalletsListRepository.getSyncStrict(userWallet.walletId) as UserWallet.Hot
|
||||||
|
|
||||||
val newKeys =
|
val newKeys =
|
||||||
result.responses.associate { ByteArrayKey(it.seedKey.publicKey) to ExtendedPublicKeysMap(it.publicKeys) }
|
result.responses.associate { ByteArrayKey(it.seedKey.publicKey) to ExtendedPublicKeysMap(it.publicKeys) }
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ class DefaultWalletsRepositoryTest {
|
||||||
repository = DefaultWalletsRepository(
|
repository = DefaultWalletsRepository(
|
||||||
appPreferencesStore = appPreferenceStore,
|
appPreferencesStore = appPreferenceStore,
|
||||||
tangemTechApi = tangemTechApi,
|
tangemTechApi = tangemTechApi,
|
||||||
userWalletsStore = mockk(),
|
userWalletsListRepository = mockk(),
|
||||||
seedPhraseNotificationVisibilityStore = mockk(),
|
seedPhraseNotificationVisibilityStore = mockk(),
|
||||||
dispatchers = dispatchers,
|
dispatchers = dispatchers,
|
||||||
authProvider = mockk(),
|
authProvider = mockk(),
|
||||||
|
|
@ -222,7 +222,7 @@ class DefaultWalletsRepositoryTest {
|
||||||
repository = DefaultWalletsRepository(
|
repository = DefaultWalletsRepository(
|
||||||
appPreferencesStore = appPreferenceStore,
|
appPreferencesStore = appPreferenceStore,
|
||||||
tangemTechApi = tangemTechApi,
|
tangemTechApi = tangemTechApi,
|
||||||
userWalletsStore = mockk(),
|
userWalletsListRepository = mockk(),
|
||||||
seedPhraseNotificationVisibilityStore = mockk(),
|
seedPhraseNotificationVisibilityStore = mockk(),
|
||||||
dispatchers = dispatchers,
|
dispatchers = dispatchers,
|
||||||
authProvider = authProvider,
|
authProvider = authProvider,
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,36 @@
|
||||||
package com.tangem.data.wallets.derivations
|
package com.tangem.data.wallets.derivations
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import arrow.core.right
|
||||||
import com.google.common.truth.Truth
|
import com.google.common.truth.Truth
|
||||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
|
||||||
import com.tangem.common.CompletionResult
|
|
||||||
import com.tangem.common.test.domain.card.MockScanResponseFactory
|
import com.tangem.common.test.domain.card.MockScanResponseFactory
|
||||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||||
import com.tangem.data.common.network.NetworkFactory
|
|
||||||
import com.tangem.data.wallets.cold.DefaultColdMapDerivationsRepository
|
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
|
||||||
import com.tangem.domain.card.ScanCardException
|
|
||||||
import com.tangem.domain.card.configs.GenericCardConfig
|
import com.tangem.domain.card.configs.GenericCardConfig
|
||||||
import com.tangem.domain.card.configs.MultiWalletCardConfig
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
|
import com.tangem.domain.models.currency.CryptoCurrency
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.operations.derivation.DerivationTaskResponse
|
import com.tangem.domain.wallets.derivations.ColdMapDerivationsRepository
|
||||||
import com.tangem.sdk.api.TangemSdkManager
|
|
||||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||||
import io.mockk.coEvery
|
import io.mockk.*
|
||||||
import io.mockk.coVerify
|
|
||||||
import io.mockk.mockk
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.jupiter.api.AfterEach
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.TestInstance
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
*/
|
*/
|
||||||
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||||
internal class DefaultDerivationsRepositoryTest {
|
internal class DefaultDerivationsRepositoryTest {
|
||||||
|
|
||||||
private val tangemSdkManager = mockk<TangemSdkManager>()
|
private val userWalletsListRepository = mockk<UserWalletsListRepository>()
|
||||||
private val userWalletsStore = mockk<UserWalletsStore>()
|
private val coldDerivationsRepository: ColdMapDerivationsRepository = mockk()
|
||||||
|
|
||||||
private val repository = DefaultDerivationsRepository(
|
private val repository = DefaultDerivationsRepository(
|
||||||
userWalletsStore = userWalletsStore,
|
userWalletsListRepository = userWalletsListRepository,
|
||||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
|
||||||
hotDerivationsRepository = mockk(),
|
hotDerivationsRepository = mockk(),
|
||||||
coldDerivationsRepository = DefaultColdMapDerivationsRepository(
|
coldDerivationsRepository = coldDerivationsRepository,
|
||||||
tangemSdkManager = tangemSdkManager,
|
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||||
networkFactory = NetworkFactory(excludedBlockchains = ExcludedBlockchains()),
|
|
||||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private val defaultUserWalletId = UserWalletId("011")
|
private val defaultUserWalletId = UserWalletId("011")
|
||||||
|
|
@ -51,127 +43,94 @@ internal class DefaultDerivationsRepositoryTest {
|
||||||
hasBackupError = false,
|
hasBackupError = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
fun tearDown() {
|
||||||
|
clearMocks(userWalletsListRepository, coldDerivationsRepository)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `error if userWalletId not found`() = runTest {
|
fun `error if userWalletId not found`() = runTest {
|
||||||
coEvery { userWalletsStore.getSyncStrict(defaultUserWalletId) } throws IllegalStateException()
|
val currencies = MockCryptoCurrencyFactory(defaultUserWallet).ethereum.let(::listOf)
|
||||||
|
coEvery { userWalletsListRepository.getSyncStrict(defaultUserWalletId) } throws IllegalStateException()
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
repository.derivePublicKeys(userWalletId = defaultUserWalletId, currencies = emptyList())
|
repository.derivePublicKeys(userWalletId = defaultUserWalletId, currencies = currencies)
|
||||||
}
|
}
|
||||||
.onSuccess { error("Should throws exception") }
|
.onSuccess { error("Should throws exception") }
|
||||||
.onFailure { Truth.assertThat(it).isInstanceOf(IllegalStateException::class.java) }
|
.onFailure { Truth.assertThat(it).isInstanceOf(IllegalStateException::class.java) }
|
||||||
|
|
||||||
coVerify(exactly = 1) { userWalletsStore.getSyncStrict(defaultUserWalletId) }
|
coVerify(exactly = 1) { userWalletsListRepository.getSyncStrict(defaultUserWalletId) }
|
||||||
coVerify(inverse = true) { tangemSdkManager.derivePublicKeys(null, any(), any()) }
|
coVerify(inverse = true) {
|
||||||
coVerify(inverse = true) { userWalletsStore.update(defaultUserWalletId, any()) }
|
coldDerivationsRepository.derivePublicKeysByNetworks(any(), any())
|
||||||
|
userWalletsListRepository.saveWithoutLock(any(), any())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("CheckResult")
|
|
||||||
@Test
|
|
||||||
fun `success if card is not supported derivations`() = runTest {
|
|
||||||
coEvery { userWalletsStore.getSyncStrict(defaultUserWalletId) } returns defaultUserWallet
|
|
||||||
|
|
||||||
repository.derivePublicKeys(userWalletId = defaultUserWalletId, currencies = emptyList())
|
|
||||||
|
|
||||||
runCatching { }
|
|
||||||
.onSuccess { Truth.assertThat(it) }
|
|
||||||
.onFailure {
|
|
||||||
error("Should returns success")
|
|
||||||
}
|
|
||||||
|
|
||||||
coVerify(exactly = 1) { userWalletsStore.getSyncStrict(defaultUserWalletId) }
|
|
||||||
coVerify(inverse = true) { tangemSdkManager.derivePublicKeys(null, any(), any()) }
|
|
||||||
coVerify(inverse = true) { userWalletsStore.update(defaultUserWalletId, any()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("CheckResult")
|
|
||||||
@Test
|
@Test
|
||||||
fun `success if currencies is empty`() = runTest {
|
fun `success if currencies is empty`() = runTest {
|
||||||
val userWallet = defaultUserWallet.copy(
|
repository.derivePublicKeys(userWalletId = defaultUserWalletId, currencies = emptyList())
|
||||||
scanResponse = MockScanResponseFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()),
|
|
||||||
)
|
|
||||||
coEvery { userWalletsStore.getSyncStrict(defaultUserWalletId) } returns userWallet
|
|
||||||
|
|
||||||
runCatching { repository.derivePublicKeys(userWalletId = defaultUserWalletId, currencies = emptyList()) }
|
coVerify(inverse = true) {
|
||||||
.onSuccess { Truth.assertThat(it) }
|
userWalletsListRepository.getSyncStrict(any())
|
||||||
.onFailure { error("Should returns success") }
|
coldDerivationsRepository.derivePublicKeysByNetworks(any(), any())
|
||||||
|
userWalletsListRepository.saveWithoutLock(any(), any())
|
||||||
coVerify(exactly = 1) { userWalletsStore.getSyncStrict(defaultUserWalletId) }
|
|
||||||
coVerify(inverse = true) { tangemSdkManager.derivePublicKeys(null, any(), any()) }
|
|
||||||
coVerify(inverse = true) { userWalletsStore.update(defaultUserWalletId, any()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("CheckResult")
|
|
||||||
@Test
|
|
||||||
fun `success if card already has derivations`() = runTest {
|
|
||||||
val userWallet = defaultUserWallet.copy(
|
|
||||||
scanResponse = MockScanResponseFactory.create(
|
|
||||||
cardConfig = MultiWalletCardConfig,
|
|
||||||
derivedKeys = DerivedKeysMocks.ethereumDerivedKeys,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
coEvery { userWalletsStore.getSyncStrict(defaultUserWalletId) } returns userWallet
|
|
||||||
|
|
||||||
runCatching {
|
|
||||||
repository.derivePublicKeys(
|
|
||||||
userWalletId = defaultUserWalletId,
|
|
||||||
currencies = MockCryptoCurrencyFactory(userWallet).ethereum.let(::listOf),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
.onSuccess { Truth.assertThat(it) }
|
|
||||||
.onFailure { error("Should returns success") }
|
|
||||||
|
|
||||||
coVerify(exactly = 1) { userWalletsStore.getSyncStrict(defaultUserWalletId) }
|
|
||||||
coVerify(inverse = true) { tangemSdkManager.derivePublicKeys(null, any(), any()) }
|
|
||||||
coVerify(inverse = true) { userWalletsStore.update(defaultUserWalletId, any()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `error if tangemSdkManager throws exception`() = runTest {
|
fun `error if coldDerivationsRepository throws exception`() = runTest {
|
||||||
val userWallet = defaultUserWallet.copy(
|
val currencies = MockCryptoCurrencyFactory(defaultUserWallet).ethereum.let(::listOf)
|
||||||
scanResponse = MockScanResponseFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()),
|
|
||||||
)
|
coEvery { userWalletsListRepository.getSyncStrict(defaultUserWalletId) } returns defaultUserWallet
|
||||||
coEvery { userWalletsStore.getSyncStrict(defaultUserWalletId) } returns userWallet
|
coEvery {
|
||||||
coEvery { tangemSdkManager.derivePublicKeys(null, any(), any()) } throws ScanCardException.UserCancelled()
|
coldDerivationsRepository.derivePublicKeysByNetworks(
|
||||||
|
userWallet = defaultUserWallet,
|
||||||
|
networks = any(),
|
||||||
|
)
|
||||||
|
} throws IllegalStateException()
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
repository.derivePublicKeys(
|
repository.derivePublicKeys(userWalletId = defaultUserWalletId, currencies = currencies)
|
||||||
userWalletId = defaultUserWalletId,
|
|
||||||
currencies = MockCryptoCurrencyFactory(userWallet).ethereum.let(::listOf),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
.onSuccess { error("Should throws exception") }
|
.onSuccess { error("Should throws exception") }
|
||||||
.onFailure { Truth.assertThat(it).isInstanceOf(ScanCardException.UserCancelled::class.java) }
|
.onFailure { Truth.assertThat(it).isInstanceOf(IllegalStateException::class.java) }
|
||||||
|
|
||||||
coVerify(exactly = 1) { userWalletsStore.getSyncStrict(defaultUserWalletId) }
|
coVerifyOrder {
|
||||||
coVerify(exactly = 1) { tangemSdkManager.derivePublicKeys(null, any(), any()) }
|
userWalletsListRepository.getSyncStrict(defaultUserWalletId)
|
||||||
coVerify(inverse = true) { userWalletsStore.update(defaultUserWalletId, any()) }
|
coldDerivationsRepository.derivePublicKeysByNetworks(
|
||||||
}
|
userWallet = defaultUserWallet,
|
||||||
|
networks = currencies.map(CryptoCurrency.Coin::network),
|
||||||
@SuppressLint("CheckResult")
|
|
||||||
@Test
|
|
||||||
fun `success case`() = runTest {
|
|
||||||
val userWallet = defaultUserWallet.copy(
|
|
||||||
scanResponse = MockScanResponseFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()),
|
|
||||||
)
|
|
||||||
coEvery { userWalletsStore.getSyncStrict(defaultUserWalletId) } returns userWallet
|
|
||||||
coEvery { tangemSdkManager.derivePublicKeys(null, any(), any()) } returns CompletionResult.Success(
|
|
||||||
DerivationTaskResponse(DerivedKeysMocks.ethereumDerivedKeys),
|
|
||||||
)
|
|
||||||
coEvery { userWalletsStore.update(defaultUserWalletId, any()) } returns CompletionResult.Success(userWallet)
|
|
||||||
|
|
||||||
runCatching {
|
|
||||||
repository.derivePublicKeys(
|
|
||||||
userWalletId = defaultUserWalletId,
|
|
||||||
currencies = MockCryptoCurrencyFactory(userWallet).ethereum.let(::listOf),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.onSuccess { Truth.assertThat(it) }
|
|
||||||
.onFailure { error("Should returns success but $it") }
|
|
||||||
|
|
||||||
coVerify(exactly = 1) { userWalletsStore.getSyncStrict(defaultUserWalletId) }
|
coVerify(inverse = true) { userWalletsListRepository.saveWithoutLock(any(), any()) }
|
||||||
coVerify(exactly = 1) { tangemSdkManager.derivePublicKeys(null, any(), any()) }
|
}
|
||||||
coVerify(exactly = 1) { userWalletsStore.update(defaultUserWalletId, any()) }
|
|
||||||
|
@Test
|
||||||
|
fun `success case`() = runTest {
|
||||||
|
val currencies = MockCryptoCurrencyFactory(defaultUserWallet).ethereum.let(::listOf)
|
||||||
|
val updatedWallet = defaultUserWallet.copy(cardsInWallet = setOf("AC01"))
|
||||||
|
|
||||||
|
coEvery { userWalletsListRepository.getSyncStrict(defaultUserWalletId) } returns defaultUserWallet
|
||||||
|
coEvery {
|
||||||
|
coldDerivationsRepository.derivePublicKeysByNetworks(
|
||||||
|
userWallet = defaultUserWallet,
|
||||||
|
networks = currencies.map(CryptoCurrency.Coin::network),
|
||||||
|
)
|
||||||
|
} returns updatedWallet
|
||||||
|
coEvery {
|
||||||
|
userWalletsListRepository.saveWithoutLock(updatedWallet, true)
|
||||||
|
} returns updatedWallet.right()
|
||||||
|
|
||||||
|
repository.derivePublicKeys(userWalletId = defaultUserWalletId, currencies = currencies)
|
||||||
|
|
||||||
|
coVerifyOrder {
|
||||||
|
userWalletsListRepository.getSyncStrict(defaultUserWalletId)
|
||||||
|
coldDerivationsRepository.derivePublicKeysByNetworks(
|
||||||
|
userWallet = defaultUserWallet,
|
||||||
|
networks = currencies.map(CryptoCurrency.Coin::network),
|
||||||
|
)
|
||||||
|
userWalletsListRepository.saveWithoutLock(updatedWallet, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.tangem.domain.common.wallets
|
||||||
|
|
||||||
|
import arrow.core.Either
|
||||||
|
import arrow.core.raise.either
|
||||||
|
import com.tangem.domain.common.wallets.error.SaveWalletError
|
||||||
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update user wallet by [userWalletId] and return updated wallet.
|
||||||
|
*
|
||||||
|
* @param userWalletId The ID of the user wallet to update.
|
||||||
|
* @param transform A function that takes the current user wallet and returns the updated version.
|
||||||
|
* @return Either containing the updated user wallet on success or an error if the update fails.
|
||||||
|
*/
|
||||||
|
suspend fun UserWalletsListRepository.update(
|
||||||
|
userWalletId: UserWalletId,
|
||||||
|
transform: suspend (UserWallet) -> UserWallet,
|
||||||
|
): Either<SaveWalletError, UserWallet> = either {
|
||||||
|
val userWallet = userWallets.value?.find { it.walletId == userWalletId }
|
||||||
|
requireNotNull(userWallet) { "Unable to find user wallet with provided ID: $userWalletId" }
|
||||||
|
|
||||||
|
val updatedUserWallet = transform(userWallet)
|
||||||
|
|
||||||
|
saveWithoutLock(
|
||||||
|
userWallet = updatedUserWallet,
|
||||||
|
canOverride = true,
|
||||||
|
)
|
||||||
|
.bind()
|
||||||
|
|
||||||
|
updatedUserWallet
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue