Updated on 2026-08-14

This commit is contained in:
Tangem 2023-11-21 12:47:53 +04:00
parent 275e07cb9d
commit 9fd43ad7fb
15 changed files with 56 additions and 502 deletions

View file

@ -54,8 +54,6 @@ import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.shop.TangemShopService
import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
import com.tangem.tap.domain.tasks.product.DerivationsFinder
import com.tangem.tap.domain.tokens.UserTokensRepository
import com.tangem.tap.domain.tokens.UserTokensStorageService
import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation
import com.tangem.tap.domain.userWalletList.di.provideRuntimeImplementation
import com.tangem.tap.domain.walletconnect.WalletConnectRepository
@ -79,7 +77,6 @@ lateinit var activityResultCaller: ActivityResultCaller
lateinit var preferencesStorage: PreferencesDataSource
lateinit var walletConnectRepository: WalletConnectRepository
lateinit var shopService: TangemShopService
internal lateinit var userTokensRepository: UserTokensRepository
internal lateinit var derivationsFinder: DerivationsFinder
@HiltAndroidApp
@ -203,18 +200,11 @@ internal class TapApplication : Application(), ImageLoaderFactory {
)
}
val userTokensStorageService = UserTokensStorageService.init(context = this)
userTokensRepository = UserTokensRepository.init(
tangemTechService = store.state.domainNetworks.tangemTechService,
networkConnectionManager = networkConnectionManager,
storageService = userTokensStorageService,
)
derivationsFinder = DerivationsFinder(
newTokensStore = userTokensStore,
dispatchers = AppCoroutineDispatcherProvider(),
)
appStateHolder.mainStore = store
appStateHolder.userTokensRepository = userTokensRepository
walletConnect2Repository.init(projectId = configManager.config.walletConnectProjectId)
}

View file

@ -1,102 +0,0 @@
package com.tangem.tap.domain.tokens
import com.squareup.moshi.JsonClass
import com.tangem.blockchain.common.Blockchain
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.domain.common.extensions.fromNetworkId
@JsonClass(generateAdapter = true)
data class CurrencyFromJson(
val id: String,
val name: String,
val symbol: String,
val networks: List<ContractFromJson>? = null,
)
@JsonClass(generateAdapter = true)
data class ContractFromJson(
val networkId: String,
val contractAddress: String?,
val decimalCount: Int?,
)
@JsonClass(generateAdapter = true)
data class CurrenciesFromJson(
val imageHost: String?,
val coins: List<CurrencyFromJson>,
)
fun List<ContractFromJson>.toContracts(): List<Contract> {
return mapNotNull { Contract.fromJsonObject(it) }
}
data class Currency(
val id: String,
val name: String,
val symbol: String,
val iconUrl: String,
val contracts: List<Contract>,
) {
companion object {
fun fromJsonObject(currency: CurrencyFromJson): Currency {
return Currency(
id = currency.id,
name = currency.name,
symbol = currency.symbol,
iconUrl = getIconUrl(currency.id, null),
contracts = currency.networks?.toContracts() ?: emptyList(),
)
}
fun fromCoinResponse(currency: CoinsResponse.Coin, imageHost: String?): Currency {
return Currency(
id = currency.id,
name = currency.name,
symbol = currency.symbol,
iconUrl = getIconUrl(currency.id, imageHost),
contracts = currency.networks.mapNotNull { Contract.fromNetwork(it, imageHost) },
)
}
}
}
data class Contract(
val networkId: String,
val blockchain: Blockchain,
val address: String?,
val decimalCount: Int?,
val iconUrl: String,
) {
companion object {
fun fromJsonObject(contract: ContractFromJson): Contract? {
val blockchain = Blockchain.fromNetworkId(contract.networkId) ?: return null
return Contract(
networkId = contract.networkId,
blockchain = blockchain,
address = contract.contractAddress,
decimalCount = contract.decimalCount,
iconUrl = getIconUrl(contract.networkId, null),
)
}
fun fromNetwork(contract: CoinsResponse.Coin.Network, imageHost: String?): Contract? {
val blockchain = Blockchain.fromNetworkId(contract.networkId) ?: return null
return Contract(
networkId = contract.networkId,
blockchain = blockchain,
address = contract.contractAddress,
decimalCount = contract.decimalCount?.toInt(),
iconUrl = getIconUrl(contract.networkId, imageHost),
)
}
}
}
fun getIconUrl(id: String, imageHost: String? = null): String {
return "${imageHost ?: DEFAULT_IMAGE_HOST}large/$id.png"
}
private const val DEFAULT_IMAGE_HOST =
"https://s3.eu-central-1.amazonaws.com/tangem.api/coins/"

View file

@ -1,146 +0,0 @@
package com.tangem.tap.domain.tokens
import com.tangem.blockchain.common.derivation.DerivationStyle
import com.tangem.common.core.TangemSdkError
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.TangemTechService
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.domain.common.BlockchainNetwork
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.userwallets.UserWalletIdBuilder
import com.tangem.tap.domain.tokens.converters.CurrencyConverter
import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.tap.features.wallet.models.toBlockchainNetworks
import com.tangem.tap.features.wallet.models.toCurrencies
import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
import timber.log.Timber
class UserTokensRepository(
private val storageService: UserTokensStorageService,
private val tangemTechApi: TangemTechApi,
private val dispatchers: CoroutineDispatcherProvider,
private val networkConnectionManager: NetworkConnectionManager,
) {
suspend fun getUserTokens(card: CardDTO, derivationStyle: DerivationStyle?): List<Currency> =
withContext(dispatchers.io) {
val userWalletId = getUserWalletId(card) ?: return@withContext emptyList()
if (DemoHelper.isDemoCardId(card.cardId)) {
return@withContext loadTokensOffline(userWalletId = userWalletId).ifEmpty {
loadDemoCurrencies(
derivationStyle,
)
}
}
if (!networkConnectionManager.isOnline) return@withContext loadTokensOffline(userWalletId = userWalletId)
return@withContext remoteGetUserTokens(userWalletId = userWalletId)
}
suspend fun saveUserTokens(card: CardDTO, tokens: List<Currency>) = withContext(dispatchers.io) {
val userWalletId = getUserWalletId(card) ?: return@withContext
val userTokens = tokens.toUserTokensResponse()
remoteSaveUserTokens(userWalletId = userWalletId, userTokens = userTokens)
storageService.saveUserTokens(userWalletId = userWalletId, tokens = userTokens)
}
// FIXME: Move to data layer
suspend fun loadBlockchainsToDerive(card: CardDTO, derivationStyle: DerivationStyle?): List<BlockchainNetwork> =
withContext(dispatchers.io) {
val userWalletId = getUserWalletId(card) ?: return@withContext emptyList()
val blockchainNetworks = loadTokensOffline(userWalletId = userWalletId).toBlockchainNetworks()
if (DemoHelper.isDemoCardId(card.cardId)) {
return@withContext blockchainNetworks.ifEmpty(loadDemoCurrencies(derivationStyle)::toBlockchainNetworks)
}
return@withContext blockchainNetworks
}
private fun loadTokensOffline(userWalletId: String): List<Currency> {
return storageService.getUserTokens(userWalletId = userWalletId) ?: emptyList()
}
// FIXME: Move to user wallet config
private fun loadDemoCurrencies(derivationStyle: DerivationStyle?): List<Currency> {
return DemoHelper.config.demoBlockchains
.map { blockchain ->
BlockchainNetwork(
blockchain = blockchain,
derivationPath = blockchain.derivationPath(derivationStyle)?.rawPath,
tokens = emptyList(),
)
}
.flatMap(BlockchainNetwork::toCurrencies)
}
private fun List<Currency>.toUserTokensResponse(): UserTokensResponse {
return UserTokensResponse(
tokens = CurrencyConverter.convertList(input = this),
group = UserTokensResponse.GroupType.NONE,
sort = UserTokensResponse.SortType.MANUAL,
)
}
private suspend fun handleGetUserTokensFailure(userWalletId: String, error: Throwable): List<Currency> {
return when {
error is TangemSdkError.NetworkError && error.customMessage.contains(NOT_FOUND_HTTP_CODE) -> {
storageService
.getUserTokens(userWalletId)
?.also { remoteSaveUserTokens(userWalletId = userWalletId, userTokens = it.toUserTokensResponse()) }
?: emptyList()
}
else -> {
storageService.getUserTokens(userWalletId)?.distinct() ?: emptyList()
}
}
}
private suspend fun remoteGetUserTokens(userWalletId: String): List<Currency> {
return runCatching { tangemTechApi.getUserTokens(userWalletId) }
.fold(
onSuccess = { response ->
response.getOrThrow()
.also { storageService.saveUserTokens(userWalletId, it) }
.tokens
.mapNotNull(Currency.Companion::fromTokenResponse)
.distinct()
},
onFailure = { handleGetUserTokensFailure(userWalletId = userWalletId, error = it) },
)
}
private suspend fun remoteSaveUserTokens(userWalletId: String, userTokens: UserTokensResponse) {
// it can throw okhttp3.internal.http2.StreamResetException: stream was reset: INTERNAL_ERROR
// if the /user-tokens endpoint disabled
runCatching { tangemTechApi.saveUserTokens(userWalletId, userTokens) }
.onFailure { Timber.e(it) }
}
private fun getUserWalletId(card: CardDTO): String? = UserWalletIdBuilder.card(card).build()?.stringValue
companion object {
private const val NOT_FOUND_HTTP_CODE = "404"
// TODO("After adding DI") get dependencies by DI
fun init(
tangemTechService: TangemTechService,
networkConnectionManager: NetworkConnectionManager,
storageService: UserTokensStorageService,
): UserTokensRepository {
return UserTokensRepository(
storageService = storageService,
tangemTechApi = tangemTechService.api,
dispatchers = AppCoroutineDispatcherProvider(),
networkConnectionManager = networkConnectionManager,
)
}
}
}

View file

@ -1,38 +0,0 @@
package com.tangem.tap.domain.tokens
import android.content.Context
import com.squareup.moshi.JsonAdapter
import com.tangem.Log
import com.tangem.datasource.api.common.MoshiConverter
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.datasource.files.AndroidFileReader
import com.tangem.datasource.files.FileReader
import com.tangem.tap.features.wallet.models.Currency
@Deprecated("Use [com.tangem.datasource.local.token.UserTokensStore] instead.")
class UserTokensStorageService(private val fileReader: FileReader) {
private val userTokensAdapter: JsonAdapter<UserTokensResponse> =
MoshiConverter.networkMoshi.adapter(UserTokensResponse::class.java)
fun getUserTokens(userWalletId: String): List<Currency>? {
return try {
val json = fileReader.readFile(getFileNameForUserTokens(userWalletId))
userTokensAdapter.fromJson(json)?.tokens?.mapNotNull { Currency.fromTokenResponse(it) }
} catch (exception: Exception) {
Log.error { exception.stackTraceToString() }
null
}
}
fun saveUserTokens(userWalletId: String, tokens: UserTokensResponse) {
val json = userTokensAdapter.toJson(tokens)
fileReader.rewriteFile(json, getFileNameForUserTokens(userWalletId))
}
companion object {
private const val FILE_NAME_PREFIX_USER_TOKENS = "user_tokens"
private fun getFileNameForUserTokens(userId: String): String = "${FILE_NAME_PREFIX_USER_TOKENS}_$userId"
fun init(context: Context) = UserTokensStorageService(AndroidFileReader(context))
}
}

View file

@ -1,20 +0,0 @@
package com.tangem.tap.domain.tokens.converters
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.utils.converter.Converter
/** Converter from domain model [Currency] to data model [UserTokensResponse.Token] */
object CurrencyConverter : Converter<Currency, UserTokensResponse.Token> {
override fun convert(value: Currency) = UserTokensResponse.Token(
id = value.coinId,
networkId = value.blockchain.toNetworkId(),
derivationPath = value.derivationPath,
name = value.currencyName,
symbol = value.currencySymbol,
decimals = value.decimals,
contractAddress = if (value is Currency.Token) value.token.contractAddress else null,
)
}

View file

@ -1,29 +0,0 @@
package com.tangem.tap.domain.tokens.models
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.blockchain.common.Blockchain
@Deprecated("The class is used only for migration from older versions of the app")
@JsonClass(generateAdapter = true)
data class BlockchainDao(
@Json(name = "key")
val name: String,
@Json(name = "testnet")
val isTestNet: Boolean,
) {
@Deprecated("The method is used only for migration from older versions of the app")
fun toBlockchain(): Blockchain {
val blockchain = Blockchain.values().find { it.name.lowercase() == name.lowercase() }
?: error("Blockchain is null")
return if (!isTestNet) blockchain else blockchain.getTestnetVersion() ?: error("Invalid BlockchainDao")
}
companion object {
@Deprecated("The method is used only for migration from older versions of the app")
fun fromBlockchain(blockchain: Blockchain): BlockchainDao {
val name = blockchain.name.removeSuffix("Testnet").lowercase()
return BlockchainDao(name, blockchain.isTestnet())
}
}
}

View file

@ -1,24 +0,0 @@
package com.tangem.tap.domain.tokens.models
import com.squareup.moshi.JsonClass
import com.tangem.blockchain.common.Blockchain
@JsonClass(generateAdapter = true)
data class ObsoleteTokenDao(
val name: String,
val symbol: String,
val contractAddress: String,
val decimalCount: Int,
val customIconUrl: String?,
) {
fun toTokenDao(blockchain: Blockchain): TokenDao {
return TokenDao(
name = name,
symbol = symbol,
contractAddress = contractAddress,
decimalCount = decimalCount,
blockchainDao = BlockchainDao.fromBlockchain(blockchain),
customIconUrl = customIconUrl,
)
}
}

View file

@ -1,29 +0,0 @@
package com.tangem.tap.domain.tokens.models
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.blockchain.common.Token
import com.tangem.tap.domain.extensions.setCustomIconUrl
@JsonClass(generateAdapter = true)
data class TokenDao(
val name: String,
val symbol: String,
val contractAddress: String,
val decimalCount: Int,
@Json(name = "blockchain")
val blockchainDao: BlockchainDao,
val customIconUrl: String? = null,
val type: String? = null,
) {
fun toToken(): Token {
return Token(
name = name,
symbol = symbol,
contractAddress = contractAddress,
decimals = decimalCount,
).apply {
customIconUrl?.let { this.setCustomIconUrl(it) }
}
}
}

View file

@ -1,22 +1,16 @@
package com.tangem.tap.features.onboarding.products.otherCards.redux
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.CompletionResult
import com.tangem.core.analytics.Analytics
import com.tangem.domain.common.BlockchainNetwork
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.common.util.derivationStyleProvider
import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.postUi
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.features.onboarding.OnboardingHelper
import com.tangem.tap.features.wallet.models.toCurrencies
import com.tangem.tap.scope
import com.tangem.tap.store
import com.tangem.tap.tangemSdkManager
import com.tangem.tap.userTokensRepository
import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@ -90,39 +84,6 @@ private fun handleOtherCardsAction(action: Action) {
onboardingManager.scanResponse = updatedResponse
onboardingManager.activationStarted(updatedCard.cardId)
val primaryBlockchain = updatedResponse.cardTypesResolver.getBlockchain()
val blockchainNetworks = if (primaryBlockchain != Blockchain.Unknown) {
val primaryToken = updatedResponse.cardTypesResolver.getPrimaryToken()
val blockchainNetwork =
BlockchainNetwork(
blockchain = primaryBlockchain,
derivationStyleProvider = updatedResponse.derivationStyleProvider,
)
.updateTokens(
listOfNotNull(primaryToken),
)
listOf(blockchainNetwork)
} else {
listOf(
BlockchainNetwork(
blockchain = Blockchain.Bitcoin,
derivationStyleProvider = updatedResponse.derivationStyleProvider,
),
BlockchainNetwork(
blockchain = Blockchain.Ethereum,
derivationStyleProvider = updatedResponse.derivationStyleProvider,
),
)
}
scope.launch {
// TODO: Use new repo [REDACTED_JIRA]
userTokensRepository.saveUserTokens(
card = result.data.card,
tokens = blockchainNetworks.toCurrencies(),
)
}
delay(DELAY_SDK_DIALOG_CLOSE)
store.dispatch(OnboardingOtherCardsAction.SetStepOfScreen(OnboardingOtherCardsStep.Done))
}

View file

@ -1,7 +1,6 @@
package com.tangem.tap.features.onboarding.products.wallet.redux
import android.net.Uri
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.guard
@ -11,11 +10,9 @@ import com.tangem.common.services.Result
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.common.BlockchainNetwork
import com.tangem.domain.common.TapWorkarounds.canSkipBackup
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.common.util.derivationStyleProvider
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.userwallets.Artwork
@ -36,7 +33,6 @@ import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.home.redux.HomeAction
import com.tangem.tap.features.onboarding.OnboardingDialog
import com.tangem.tap.features.onboarding.OnboardingHelper
import com.tangem.tap.features.wallet.models.toCurrencies
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.wallet.R
import kotlinx.coroutines.launch
@ -143,24 +139,6 @@ private fun handleWalletAction(action: Action) {
)
onboardingManager.scanResponse = updatedResponse
val blockchainNetworks = if (DemoHelper.isDemoCardId(result.data.card.cardId)) {
DemoHelper.config.demoBlockchains
} else {
listOf(Blockchain.Bitcoin, Blockchain.Ethereum)
}.map { blockchain ->
BlockchainNetwork(
blockchain = blockchain,
derivationStyleProvider = updatedResponse.derivationStyleProvider,
)
}
scope.launch {
// TODO: Use new repo [REDACTED_JIRA]
userTokensRepository.saveUserTokens(
card = result.data.card,
tokens = blockchainNetworks.toCurrencies(),
)
}
startCardActivation(updatedResponse)
store.dispatch(OnboardingWalletAction.ResumeBackup)
}

View file

@ -3,7 +3,6 @@ package com.tangem.tap.features.tokens.impl.data.converters
import com.tangem.blockchain.common.Blockchain
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.tap.domain.tokens.getIconUrl
import com.tangem.tap.features.tokens.impl.domain.models.Token
import com.tangem.utils.converter.Converter
@ -14,6 +13,8 @@ import com.tangem.utils.converter.Converter
*/
internal object CoinsResponseConverter : Converter<CoinsResponse, List<Token>> {
private const val DEFAULT_IMAGE_HOST = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/"
override fun convert(value: CoinsResponse): List<Token> {
return value.coins.map { token ->
Token(
@ -35,4 +36,8 @@ internal object CoinsResponseConverter : Converter<CoinsResponse, List<Token>> {
)
}
}
fun getIconUrl(id: String, imageHost: String? = null): String {
return "${imageHost ?: DEFAULT_IMAGE_HOST}large/$id.png"
}
}

View file

@ -3,7 +3,6 @@ package com.tangem.tap.features.tokens.impl.data.converters
import com.tangem.blockchain.common.Blockchain
import com.tangem.datasource.local.testnet.models.TestnetTokensConfig
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.tap.domain.tokens.getIconUrl
import com.tangem.tap.features.tokens.impl.domain.models.Token
import com.tangem.utils.converter.Converter
@ -20,7 +19,7 @@ internal object TestnetTokensConfigConverter : Converter<TestnetTokensConfig, Li
id = token.id,
name = token.name,
symbol = token.symbol,
iconUrl = getIconUrl(id = token.id, imageHost = null),
iconUrl = CoinsResponseConverter.getIconUrl(token.id),
networks = token.networks?.mapNotNull { network ->
val blockchain = Blockchain.fromNetworkId(network.id) ?: return@mapNotNull null
@ -28,7 +27,7 @@ internal object TestnetTokensConfigConverter : Converter<TestnetTokensConfig, Li
id = network.id,
blockchain = blockchain,
address = network.address,
iconUrl = getIconUrl(id = network.id, imageHost = null),
iconUrl = CoinsResponseConverter.getIconUrl(network.id),
decimalCount = network.decimalCount,
)
}.orEmpty(),

View file

@ -14,7 +14,6 @@ import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.onUserWalletSelected
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.domain.TangemSdkManager
import com.tangem.tap.domain.tokens.UserTokensRepository
import com.tangem.tap.network.exchangeServices.ExchangeService
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@ -41,7 +40,6 @@ class AppStateHolder @Inject constructor() : WalletsStateHolder, ReduxNavControl
@Deprecated("Use scan response from selected user wallet")
var scanResponse: ScanResponse? = null
var userTokensRepository: UserTokensRepository? = null
var mainStore: Store<AppState>? = null
var tangemSdkManager: TangemSdkManager? = null
var appFiatCurrency: FiatCurrency = FiatCurrency.Default

View file

@ -4,9 +4,12 @@ import com.tangem.blockchain.common.AmountType
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
import com.tangem.blockchain.common.WalletManager
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.domain.common.extensions.toCoinId
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.lib.crypto.UserWalletManager
import com.tangem.lib.crypto.models.Currency
@ -21,6 +24,8 @@ import java.math.BigDecimal
class UserWalletManagerImpl(
private val appStateHolder: AppStateHolder,
private val walletManagersFacade: WalletManagersFacade,
private val currenciesRepository: CurrenciesRepository,
private val userWalletsStore: UserWalletsStore,
) : UserWalletManager {
override suspend fun getUserTokens(
@ -28,43 +33,44 @@ class UserWalletManagerImpl(
derivationPath: String?,
isExcludeCustom: Boolean,
): List<Currency> {
val card = appStateHolder.getActualCard()
val userTokensRepository =
requireNotNull(appStateHolder.userTokensRepository) { "userTokensRepository is null" }
return if (card != null) {
userTokensRepository.getUserTokens(card, null) // refactor in [REDACTED_JIRA]
.filter {
val checkCustom = if (isExcludeCustom) {
!it.isCustomCurrency(null)
} else {
true
}
it.blockchain.toNetworkId() == networkId &&
checkCustom &&
it.derivationPath == derivationPath
}
.map {
if (it is com.tangem.tap.features.wallet.models.Currency.Token) {
NonNativeToken(
id = it.coinId ?: "",
name = it.currencyName,
symbol = it.currencySymbol,
networkId = it.blockchain.toNetworkId(),
contractAddress = it.token.contractAddress,
decimalCount = it.token.decimals,
)
} else {
NativeToken(
id = it.coinId ?: "",
name = it.currencyName,
symbol = it.currencySymbol,
networkId = it.blockchain.toNetworkId(),
)
}
}
} else {
emptyList()
// FIXME: Find user wallet by ID
val userWallet = requireNotNull(userWalletsStore.selectedUserWalletOrNull) {
"No user wallet selected"
}
return currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWallet.walletId)
.filter {
val checkCustom = if (isExcludeCustom) {
!it.isCustom
} else {
true
}
val blockchain = Blockchain.fromId(it.network.id.value)
blockchain.toNetworkId() == networkId &&
checkCustom &&
it.network.derivationPath.value == derivationPath
}
.map {
val blockchain = Blockchain.fromId(it.network.id.value)
if (it is CryptoCurrency.Token) {
NonNativeToken(
id = it.id.rawCurrencyId ?: "",
name = it.name,
symbol = it.symbol,
networkId = blockchain.toNetworkId(),
contractAddress = it.contractAddress,
decimalCount = it.decimals,
)
} else {
NativeToken(
id = it.id.rawCurrencyId ?: "",
name = it.name,
symbol = it.symbol,
networkId = blockchain.toNetworkId(),
)
}
}
}
override fun getNativeTokenForNetwork(networkId: String): Currency {

View file

@ -2,6 +2,7 @@ package com.tangem.tap.proxy.di
import com.tangem.common.Provider
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.common.CardTypesResolver
import com.tangem.domain.common.util.cardTypesResolver
@ -23,7 +24,7 @@ import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
class ProxyModule {
internal object ProxyModule {
@Provides
@Singleton
@ -36,10 +37,14 @@ class ProxyModule {
fun provideUserWalletManager(
appStateHolder: AppStateHolder,
walletManagersFacade: WalletManagersFacade,
currenciesRepository: CurrenciesRepository,
userWalletsStore: UserWalletsStore,
): UserWalletManager {
return UserWalletManagerImpl(
appStateHolder = appStateHolder,
walletManagersFacade = walletManagersFacade,
currenciesRepository = currenciesRepository,
userWalletsStore = userWalletsStore,
)
}