Updated on 2026-08-14

This commit is contained in:
Tangem 2023-09-21 17:15:05 +03:00
parent 879c8d603b
commit af8fc1732d
14 changed files with 215 additions and 187 deletions

View file

@ -22,6 +22,7 @@ import com.tangem.datasource.config.ConfigManager
import com.tangem.datasource.config.FeaturesLocalLoader
import com.tangem.datasource.config.models.Config
import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.datasource.local.token.UserTokensStore
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
@ -50,7 +51,9 @@ import com.tangem.tap.common.redux.appReducer
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.totalBalance.TotalFiatBalanceCalculator
import com.tangem.tap.domain.totalBalance.di.provideDefaultImplementation
import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
@ -67,6 +70,7 @@ import com.tangem.tap.features.details.DarkThemeFeatureToggle
import com.tangem.tap.features.details.featuretoggles.DetailsFeatureToggles
import com.tangem.tap.proxy.AppStateHolder
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider
import com.tangem.wallet.BuildConfig
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.runBlocking
@ -82,7 +86,8 @@ lateinit var activityResultCaller: ActivityResultCaller
lateinit var preferencesStorage: PreferencesDataSource
lateinit var walletConnectRepository: WalletConnectRepository
lateinit var shopService: TangemShopService
lateinit var userTokensRepository: UserTokensRepository
internal lateinit var userTokensRepository: UserTokensRepository
internal lateinit var derivationsFinder: DerivationsFinder
private val walletStoresRepository by lazy { WalletStoresRepository.provideDefaultImplementation() }
private val walletManagersRepository by lazy {
@ -123,8 +128,9 @@ val totalFiatBalanceCalculator by lazy {
}
@HiltAndroidApp
class TapApplication : Application(), ImageLoaderFactory {
internal class TapApplication : Application(), ImageLoaderFactory {
// region Injected
@Inject
lateinit var appStateHolder: AppStateHolder
@ -188,6 +194,10 @@ class TapApplication : Application(), ImageLoaderFactory {
@Inject
lateinit var darkThemeFeatureToggle: DarkThemeFeatureToggle
@Inject
lateinit var userTokensStore: UserTokensStore
// endregion Injected
override fun onCreate() {
super.onCreate()
@ -247,10 +257,17 @@ class TapApplication : Application(), ImageLoaderFactory {
)
}
val userTokensStorageService = UserTokensStorageService.init(context = this)
userTokensRepository = UserTokensRepository.init(
context = this,
tangemTechService = store.state.domainNetworks.tangemTechService,
networkConnectionManager = networkConnectionManager,
storageService = userTokensStorageService,
)
derivationsFinder = DerivationsFinder(
legacyTokensStore = userTokensStorageService,
newTokensStore = userTokensStore,
walletFeatureToggles = walletFeatureToggles,
dispatchers = AppCoroutineDispatcherProvider(),
)
appStateHolder.mainStore = store
appStateHolder.userTokensRepository = userTokensRepository

View file

@ -1,9 +1,7 @@
package com.tangem.tap.common.redux.global
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.WalletManager
import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemError
import com.tangem.datasource.config.ConfigManager
import com.tangem.datasource.config.models.ChatConfig
import com.tangem.domain.apptheme.model.AppThemeMode
@ -49,13 +47,6 @@ sealed class GlobalAction : Action {
object Stop : Onboarding()
}
data class ScanCard(
val additionalBlockchainsToDerive: Collection<Blockchain>? = null,
val onSuccess: ((ScanResponse) -> Unit)? = null,
val onFailure: ((TangemError) -> Unit)? = null,
val messageResId: Int? = null,
) : GlobalAction()
object ScanFailsCounter {
data class ChooseBehavior(val result: CompletionResult<ScanResponse>) : GlobalAction()
object Reset : GlobalAction()

View file

@ -5,10 +5,8 @@ import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.guard
import com.tangem.datasource.config.models.Config
import com.tangem.domain.common.LogConfig
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.tap.*
import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
import com.tangem.tap.common.extensions.dispatchDialogShow
@ -26,7 +24,11 @@ import com.tangem.tap.network.exchangeServices.ExchangeService
import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoEnvironment
import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoService
import com.tangem.tap.network.exchangeServices.moonpay.MoonPayService
import com.tangem.tap.preferencesStorage
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.scope
import com.tangem.tap.store
import com.tangem.tap.walletCurrenciesManager
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import org.rekotlin.Action
@ -151,28 +153,6 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di
}
scope.launch { exchangeManager.update() }
}
is GlobalAction.ScanCard -> {
scope.launch {
tangemSdkManager.changeDisplayedCardIdNumbersCount(null)
val result = tangemSdkManager.scanProduct(
userTokensRepository = userTokensRepository,
additionalBlockchainsToDerive = action.additionalBlockchainsToDerive,
messageRes = action.messageResId,
)
withMainContext {
store.dispatch(GlobalAction.ScanFailsCounter.ChooseBehavior(result))
when (result) {
is CompletionResult.Success -> {
tangemSdkManager.changeDisplayedCardIdNumbersCount(result.data)
action.onSuccess?.invoke(result.data)
}
is CompletionResult.Failure -> {
action.onFailure?.invoke(result.error)
}
}
}
}
}
is GlobalAction.FetchUserCountry -> {
scope.launch {
// TODO("After adding DI") get dependencies by DI

View file

@ -8,7 +8,6 @@ import com.tangem.tap.domain.TangemSdkManager
import com.tangem.tap.domain.scanCard.repository.DefaultScanCardRepository
import com.tangem.tap.network.exchangeServices.DefaultRampManager
import com.tangem.tap.proxy.AppStateHolder
import com.tangem.tap.userTokensRepository
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -38,7 +37,6 @@ internal object ActivityModule {
return ScanCardUseCase(
cardSdkConfigRepository = cardSdkConfigRepository,
scanCardRepository = DefaultScanCardRepository(
userTokensRepository = userTokensRepository,
tangemSdkManager = tangemSdkManager,
),
)

View file

@ -4,7 +4,6 @@ import android.content.res.Resources
import androidx.annotation.StringRes
import com.tangem.Message
import com.tangem.TangemSdk
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.*
import com.tangem.common.biometric.BiometricManager
import com.tangem.common.card.FirmwareVersion
@ -25,12 +24,12 @@ import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
import com.tangem.operations.pins.SetUserCodeCommand
import com.tangem.operations.usersetttings.SetUserCodeRecoveryAllowedTask
import com.tangem.tap.common.analytics.events.Basic
import com.tangem.tap.derivationsFinder
import com.tangem.tap.domain.tasks.CreateWalletAndRescanTask
import com.tangem.tap.domain.tasks.product.CreateProductWalletTask
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
import com.tangem.tap.domain.tasks.product.ResetToFactorySettingsTask
import com.tangem.tap.domain.tasks.product.ScanProductTask
import com.tangem.tap.domain.tokens.UserTokensRepository
import com.tangem.wallet.R
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.suspendCancellableCoroutine
@ -38,7 +37,10 @@ import kotlinx.coroutines.withContext
import kotlin.coroutines.resume
@Suppress("TooManyFunctions")
class TangemSdkManager(private val cardSdkConfigRepository: CardSdkConfigRepository, private val resources: Resources) {
class TangemSdkManager(
private val cardSdkConfigRepository: CardSdkConfigRepository,
private val resources: Resources,
) {
private val tangemSdk: TangemSdk
get() = cardSdkConfigRepository.sdk
@ -60,9 +62,7 @@ class TangemSdkManager(private val cardSdkConfigRepository: CardSdkConfigReposit
get() = tangemSdk.biometricManager
suspend fun scanProduct(
userTokensRepository: UserTokensRepository,
cardId: String? = null,
additionalBlockchainsToDerive: Collection<Blockchain>? = null,
messageRes: Int? = null,
allowsRequestAccessCodeFromRepository: Boolean = false,
): CompletionResult<ScanResponse> {
@ -70,8 +70,7 @@ class TangemSdkManager(private val cardSdkConfigRepository: CardSdkConfigReposit
return runTaskAsyncReturnOnMain(
runnable = ScanProductTask(
card = null,
userTokensRepository = userTokensRepository,
additionalBlockchainsToDerive = additionalBlockchainsToDerive,
derivationsFinder = derivationsFinder,
allowsRequestAccessCodeFromRepository = allowsRequestAccessCodeFromRepository,
),
cardId = cardId,

View file

@ -15,7 +15,10 @@ import com.tangem.domain.common.util.twinsIsTwinned
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.tap.*
import com.tangem.tap.common.analytics.paramsInterceptor.CardContextInterceptor
import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.extensions.addContext
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.extensions.setContext
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.features.disclaimer.createDisclaimer
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
@ -34,8 +37,7 @@ internal object LegacyScanProcessor {
allowsRequestAccessCodeFromRepository: Boolean = false,
): CompletionResult<ScanResponse> {
return tangemSdkManager.scanProduct(
userTokensRepository,
cardId,
cardId = cardId,
allowsRequestAccessCodeFromRepository = allowsRequestAccessCodeFromRepository,
)
}
@ -56,10 +58,7 @@ internal object LegacyScanProcessor {
tangemSdkManager.changeDisplayedCardIdNumbersCount(null)
val result = tangemSdkManager.scanProduct(
userTokensRepository = userTokensRepository,
cardId = cardId,
)
val result = tangemSdkManager.scanProduct(cardId)
store.dispatchOnMain(GlobalAction.ScanFailsCounter.ChooseBehavior(result))

View file

@ -8,13 +8,8 @@ import com.tangem.domain.card.repository.ScanCardRepository
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.tap.domain.TangemSdkManager
import com.tangem.tap.domain.scanCard.utils.ScanCardExceptionConverter
import com.tangem.tap.domain.tokens.UserTokensRepository
internal class DefaultScanCardRepository(
// FIXME: The repository should not depend on another repository.
// But now we need to provide loadBlockchainsToDerive() to ScanProductTask and it's hard to move this method from
// UserTokensRepository.
private val userTokensRepository: UserTokensRepository,
private val tangemSdkManager: TangemSdkManager,
) : ScanCardRepository {
@ -27,7 +22,6 @@ internal class DefaultScanCardRepository(
when (
val result = tangemSdkManager.scanProduct(
cardId = cardId,
userTokensRepository = userTokensRepository,
allowsRequestAccessCodeFromRepository = allowRequestAccessCodeFromStorage,
)
) {

View file

@ -303,7 +303,7 @@ private class CreateWalletTangemWallet(
private fun getBlockchains(cardId: String, card: CardDTO): List<Blockchain> {
return when {
DemoHelper.isDemoCardId(cardId) -> DemoHelper.config.demoBlockchains
DemoHelper.isDemoCardId(cardId) -> DemoHelper.config.demoBlockchains.toList()
card.isTestCard -> listOf(Blockchain.BitcoinTestnet, Blockchain.EthereumTestnet)
else -> listOf(Blockchain.Bitcoin, Blockchain.Ethereum)
}

View file

@ -0,0 +1,159 @@
package com.tangem.tap.domain.tasks.product
import com.tangem.blockchain.blockchains.cardano.CardanoUtils
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.derivation.DerivationStyle
import com.tangem.crypto.hdWallet.DerivationPath
import com.tangem.datasource.local.token.UserTokensStore
import com.tangem.domain.common.DerivationStyleProvider
import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.userwallets.UserWalletIdBuilder
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import com.tangem.tap.domain.tokens.UserTokensStorageService
import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
internal data class BlockchainToDerive(
val blockchain: Blockchain,
val derivationPath: DerivationPath?,
)
// FIXME: May be move to DI, currently unnecessary
internal class DerivationsFinder(
private val legacyTokensStore: UserTokensStorageService,
private val newTokensStore: UserTokensStore,
private val walletFeatureToggles: WalletFeatureToggles,
private val dispatchers: CoroutineDispatcherProvider,
) {
suspend fun findBlockchainsToDerive(
card: CardDTO,
derivationStyleProvider: DerivationStyleProvider,
): Set<BlockchainToDerive> {
if (!card.settings.isHDWalletAllowed || card.wallets.isEmpty()) return emptySet()
val userWalletId = UserWalletIdBuilder.card(card).build() ?: return emptySet()
val derivationStyle = derivationStyleProvider.getDerivationStyle()
var blockchains = withContext(dispatchers.io) {
if (walletFeatureToggles.isRedesignedScreenEnabled) {
getBlockchainsNew(userWalletId)
} else {
getBlockchainsLegacy(userWalletId)
}
}
if (blockchains.isEmpty()) {
blockchains = if (DemoHelper.isDemoCardId(card.cardId)) {
getDemoBlockchains(derivationStyle)
} else {
getDefaultBlockchains(derivationStyle)
}
}
// we should generate second key for cardano
// because cardano address generation for wallet2 requires keys from 2 derivations
// https://developers.cardano.org/docs/get-started/cardano-serialization-lib/generating-keys/
blockchains.addSecondCardanoDerivationIfPresent()
if (card.settings.isHDWalletAllowed) {
blockchains.addEthereumBlockchains(derivationStyle)
}
// pay attention to this
if (!card.useOldStyleDerivation) {
blockchains.removeUnnecessaryBlockchains()
}
return blockchains
}
private suspend fun getBlockchainsNew(userWalletId: UserWalletId): MutableSet<BlockchainToDerive> {
val responseTokens = newTokensStore.getSyncOrNull(userWalletId)
?.tokens
?: return hashSetOf()
return responseTokens.asSequence()
.filter { it.contractAddress == null }
.mapNotNull { coin ->
val blockchain = Blockchain.fromNetworkId(coin.networkId) ?: return@mapNotNull null
val derivationPath = coin.derivationPath?.let(::DerivationPath)
BlockchainToDerive(blockchain, derivationPath)
}
.toMutableSet()
}
private fun getBlockchainsLegacy(userWalletId: UserWalletId): MutableSet<BlockchainToDerive> {
val currencies = legacyTokensStore.getUserTokens(userWalletId.stringValue)
?.takeIf { it.isNotEmpty() }
?: return hashSetOf()
return currencies.asSequence()
.filterIsInstance<Currency.Blockchain>()
.map { coin ->
val blockchain = coin.blockchain
val derivationPath = coin.derivationPath?.let(::DerivationPath)
BlockchainToDerive(blockchain, derivationPath)
}
.toMutableSet()
}
// TODO: Move to user wallet config
private fun getDemoBlockchains(derivationStyle: DerivationStyle?): MutableSet<BlockchainToDerive> {
return DemoHelper.config.demoBlockchains.mapToBlockchainsWithDerivations(derivationStyle)
}
// TODO: Move to user wallet config
private fun getDefaultBlockchains(derivationStyle: DerivationStyle?): MutableSet<BlockchainToDerive> {
val defaultBlockchains = setOf(Blockchain.Bitcoin, Blockchain.Ethereum)
return defaultBlockchains.mapToBlockchainsWithDerivations(derivationStyle)
}
}
private fun MutableSet<BlockchainToDerive>.addEthereumBlockchains(derivationStyle: DerivationStyle?) {
val ethereumBlockchains = setOf(Blockchain.Ethereum, Blockchain.EthereumTestnet)
.mapToBlockchainsWithDerivations(derivationStyle)
addAll(ethereumBlockchains)
}
private fun MutableSet<BlockchainToDerive>.removeUnnecessaryBlockchains() {
val unnecessaryBlockchains = listOf(
Blockchain.BSC, Blockchain.BSCTestnet,
Blockchain.Polygon, Blockchain.PolygonTestnet,
Blockchain.RSK,
Blockchain.Fantom, Blockchain.FantomTestnet,
Blockchain.Avalanche, Blockchain.AvalancheTestnet,
)
removeAll { it.blockchain in unnecessaryBlockchains }
}
private fun MutableSet<BlockchainToDerive>.addSecondCardanoDerivationIfPresent() {
val cardanoDerivation = this
.firstOrNull { it.blockchain == Blockchain.Cardano }
?.derivationPath
?: return
val secondCardanoBlockchain = BlockchainToDerive(
blockchain = Blockchain.Cardano,
derivationPath = CardanoUtils.extendedDerivationPath(cardanoDerivation),
)
add(secondCardanoBlockchain)
}
private fun Set<Blockchain>.mapToBlockchainsWithDerivations(
derivationStyle: DerivationStyle?,
): MutableSet<BlockchainToDerive> {
return mapTo(hashSetOf()) { blockchain ->
BlockchainToDerive(blockchain, blockchain.derivationPath(derivationStyle))
}
}

View file

@ -1,7 +1,5 @@
package com.tangem.tap.domain.tasks.product
import com.tangem.blockchain.blockchains.cardano.CardanoUtils
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.CompletionResult
import com.tangem.common.card.Card
import com.tangem.common.card.FirmwareVersion
@ -15,13 +13,11 @@ import com.tangem.common.tlv.Tlv
import com.tangem.common.tlv.TlvDecoder
import com.tangem.crypto.CryptoUtils
import com.tangem.crypto.hdWallet.DerivationPath
import com.tangem.domain.common.BlockchainNetwork
import com.tangem.domain.common.DerivationStyleProvider
import com.tangem.domain.common.TapWorkarounds.isExcluded
import com.tangem.domain.common.TapWorkarounds.isNotSupportedInThatRelease
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation
import com.tangem.domain.common.TwinsHelper
import com.tangem.domain.common.configs.CardConfig
import com.tangem.domain.common.util.derivationStyleProvider
@ -35,16 +31,14 @@ import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
import com.tangem.operations.files.ReadFilesTask
import com.tangem.operations.issuerAndUserData.ReadIssuerDataCommand
import com.tangem.tap.domain.TapSdkError
import com.tangem.tap.domain.tokens.UserTokensRepository
import com.tangem.tap.preferencesStorage
import com.tangem.tap.scope
import kotlinx.coroutines.launch
import kotlin.collections.set
class ScanProductTask(
val card: Card? = null,
private val userTokensRepository: UserTokensRepository?,
private val additionalBlockchainsToDerive: Collection<Blockchain>? = null,
internal class ScanProductTask(
private val card: Card?,
private val derivationsFinder: DerivationsFinder?,
override val allowsRequestAccessCodeFromRepository: Boolean = false,
) : CardSessionRunnable<ScanResponse> {
@ -63,14 +57,14 @@ class ScanProductTask(
val commandProcessor = when {
cardDto.isTangemTwins -> ScanTwinProcessor()
else -> ScanWalletProcessor(userTokensRepository, additionalBlockchainsToDerive)
else -> ScanWalletProcessor(derivationsFinder)
}
commandProcessor.proceed(cardDto, session) { processorResult ->
when (processorResult) {
is CompletionResult.Success -> ScanTask().run(session) { scanTaskResult ->
when (scanTaskResult) {
is CompletionResult.Success -> {
// it need because processorResult.data.card doesn't contains attestation result
// it needed because processorResult.data.card doesn't contains attestation result
// and CardWallet.derivedKeys
val processorScanResponseWithNewCard = processorResult.data.copy(
card = CardDTO(scanTaskResult.data),
@ -99,8 +93,7 @@ class ScanProductTask(
}
private class ScanWalletProcessor(
private val userTokensRepository: UserTokensRepository?,
private val additionalBlockchainsToDerive: Collection<Blockchain>? = null,
private val derivationsFinder: DerivationsFinder?,
) : ProductCommandProcessor<ScanResponse> {
var primaryCard: PrimaryCard? = null
@ -244,120 +237,15 @@ private class ScanWalletProcessor(
}
}
private suspend fun getBlockchainsToDerive(
card: CardDTO,
derivationStyleProvider: DerivationStyleProvider,
): List<BlockchainNetwork> {
val userTokensRepository = userTokensRepository ?: return emptyList()
val blockchainsToDerive = userTokensRepository.loadBlockchainsToDerive(
card,
derivationStyleProvider.getDerivationStyle(),
)
.toMutableList()
.ifEmpty { getDefaultBlockchains(derivationStyleProvider) }
if (card.settings.isHDWalletAllowed) {
blockchainsToDerive += getEthereumBlockchains(derivationStyleProvider)
}
additionalBlockchainsToDerive?.let {
blockchainsToDerive += getAdditionalBlockchainToDerive(derivationStyleProvider, it)
}
// we should generate second key for cardano
// because cardano address generation for wallet2 requires keys from 2 derivations
// https://developers.cardano.org/docs/get-started/cardano-serialization-lib/generating-keys/
val secondCardanoNetwork = blockchainsToDerive
.find { it.blockchain == Blockchain.Cardano }
?.let { getCardanoSecondNetwork(it) }
secondCardanoNetwork?.let { blockchainsToDerive.add(it) }
// pay attention to this
if (!card.useOldStyleDerivation) {
removeUnnecessaryBlockchains(blockchainsToDerive, derivationStyleProvider)
}
return blockchainsToDerive.distinct()
}
private fun getDefaultBlockchains(
derivationStyleProvider: DerivationStyleProvider,
): MutableList<BlockchainNetwork> {
return mutableListOf(
BlockchainNetwork(
blockchain = Blockchain.Bitcoin,
derivationStyleProvider = derivationStyleProvider,
),
BlockchainNetwork(
blockchain = Blockchain.Ethereum,
derivationStyleProvider = derivationStyleProvider,
),
)
}
private fun getEthereumBlockchains(derivationStyleProvider: DerivationStyleProvider): List<BlockchainNetwork> {
return listOf(
BlockchainNetwork(
blockchain = Blockchain.Ethereum,
derivationStyleProvider = derivationStyleProvider,
),
BlockchainNetwork(
blockchain = Blockchain.EthereumTestnet,
derivationStyleProvider = derivationStyleProvider,
),
)
}
private fun getAdditionalBlockchainToDerive(
derivationStyleProvider: DerivationStyleProvider,
collection: Collection<Blockchain>,
): List<BlockchainNetwork> {
return collection.map {
BlockchainNetwork(
blockchain = it,
derivationStyleProvider = derivationStyleProvider,
)
}
}
private fun getCardanoSecondNetwork(cardanoBlockchainNetwork: BlockchainNetwork): BlockchainNetwork? {
val cardanoStandardDerivation = cardanoBlockchainNetwork.derivationPath?.let { DerivationPath(it) }
?: return null
val cardanoPatchedDerivation = CardanoUtils.extendedDerivationPath(cardanoStandardDerivation)
return BlockchainNetwork(
blockchain = Blockchain.Cardano,
derivationPath = cardanoPatchedDerivation.rawPath,
tokens = emptyList(),
)
}
private fun removeUnnecessaryBlockchains(
blockchainsToDerive: MutableList<BlockchainNetwork>,
derivationStyleProvider: DerivationStyleProvider,
) {
blockchainsToDerive.removeAll(
listOf(
Blockchain.BSC, Blockchain.BSCTestnet,
Blockchain.Polygon, Blockchain.PolygonTestnet,
Blockchain.RSK,
Blockchain.Fantom, Blockchain.FantomTestnet,
Blockchain.Avalanche, Blockchain.AvalancheTestnet,
).map {
BlockchainNetwork(
blockchain = it,
derivationStyleProvider = derivationStyleProvider,
)
},
)
}
private suspend fun collectDerivations(
card: CardDTO,
config: CardConfig,
derivationStyleProvider: DerivationStyleProvider,
): Map<ByteArrayKey, List<DerivationPath>> {
val blockchains = getBlockchainsToDerive(card, derivationStyleProvider)
val derivations = mutableMapOf<ByteArrayKey, List<DerivationPath>>()
val blockchains = derivationsFinder
?.findBlockchainsToDerive(card, derivationStyleProvider)
?: return derivations
blockchains.forEach { blockchain ->
val curve = config.primaryCurve(blockchain.blockchain)
@ -365,7 +253,7 @@ private class ScanWalletProcessor(
if (wallet.chainCode == null) return@forEach
val key = wallet.publicKey.toMapKey()
val path = blockchain.derivationPath?.let { DerivationPath(it) }
val path = blockchain.derivationPath
if (path != null) {
val addedDerivations = derivations[key]
if (addedDerivations != null) {
@ -375,6 +263,7 @@ private class ScanWalletProcessor(
}
}
}
return derivations
}
}

View file

@ -1,13 +1,11 @@
package com.tangem.tap.domain.tokens
import android.content.Context
import com.tangem.blockchain.common.derivation.DerivationStyle
import com.tangem.common.core.TangemSdkError
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.datasource.files.AndroidFileReader
import com.tangem.domain.common.BlockchainNetwork
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.userwallets.UserWalletIdBuilder
@ -131,12 +129,12 @@ class UserTokensRepository(
// TODO("After adding DI") get dependencies by DI
fun init(
context: Context,
tangemTechService: TangemTechService,
networkConnectionManager: NetworkConnectionManager,
storageService: UserTokensStorageService,
): UserTokensRepository {
return UserTokensRepository(
storageService = UserTokensStorageService(fileReader = AndroidFileReader(context)),
storageService = storageService,
tangemTechApi = tangemTechService.api,
dispatchers = AppCoroutineDispatcherProvider(),
networkConnectionManager = networkConnectionManager,

View file

@ -1,9 +1,11 @@
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
@ -30,5 +32,7 @@ class UserTokensStorageService(private val fileReader: FileReader) {
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

@ -23,7 +23,7 @@ class FinalizeTwinTask(
PreflightReadTask(PreflightReadMode.FullCardRead).run(session) { readResult ->
when (readResult) {
is CompletionResult.Success ->
ScanProductTask(readResult.data, null)
ScanProductTask(readResult.data, derivationsFinder = null)
.run(session, callback)
is CompletionResult.Failure ->
callback(CompletionResult.Failure(readResult.error))

View file

@ -9,7 +9,7 @@ import java.math.BigDecimal
@Suppress("LargeClass")
class DemoConfig {
val demoBlockchains = listOf(
val demoBlockchains = setOf(
Blockchain.Bitcoin,
Blockchain.Ethereum,
Blockchain.Dogecoin,