Updated on 2026-08-14
This commit is contained in:
parent
275e07cb9d
commit
9fd43ad7fb
15 changed files with 56 additions and 502 deletions
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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/"
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue