Updated on 2026-08-14

This commit is contained in:
Tangem 2022-09-17 15:04:50 +04:00
parent 4d73b7725e
commit d8be65f5f7
41 changed files with 983 additions and 767 deletions

View file

@ -32,16 +32,14 @@ import com.tangem.operations.issuerAndUserData.ReadIssuerDataCommand
import com.tangem.tap.domain.TapSdkError
import com.tangem.tap.domain.extensions.getPrimaryCurve
import com.tangem.tap.domain.extensions.getSingleWallet
import com.tangem.tap.domain.tokens.CurrenciesRepository
import com.tangem.tap.domain.tokens.UserTokensRepository
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.preferencesStorage
import com.tangem.tap.scope
import kotlinx.coroutines.launch
class ScanProductTask(
val card: Card? = null,
private val currenciesRepository: CurrenciesRepository?,
private val additionalBlockchainsToDerive: Collection<Blockchain>? = null
private val userTokensRepository: UserTokensRepository?,
private val additionalBlockchainsToDerive: Collection<Blockchain>? = null,
) : CardSessionRunnable<ScanResponse> {
override fun run(
@ -62,7 +60,7 @@ class ScanProductTask(
val commandProcessor = when {
card.isTangemNote() -> ScanNoteProcessor()
card.isTangemTwins() -> ScanTwinProcessor()
else -> ScanWalletProcessor(currenciesRepository, additionalBlockchainsToDerive)
else -> ScanWalletProcessor(userTokensRepository, additionalBlockchainsToDerive)
}
commandProcessor.proceed(card, session) { processorResult ->
when (processorResult) {
@ -111,8 +109,8 @@ private class ScanNoteProcessor : ProductCommandProcessor<ScanResponse> {
}
private class ScanWalletProcessor(
private val currenciesRepository: CurrenciesRepository?,
private val additionalBlockchainsToDerive: Collection<Blockchain>? = null
private val userTokensRepository: UserTokensRepository?,
private val additionalBlockchainsToDerive: Collection<Blockchain>? = null,
) : ProductCommandProcessor<ScanResponse> {
var primaryCard: PrimaryCard? = null
@ -184,47 +182,41 @@ private class ScanWalletProcessor(
session: CardSession,
callback: (result: CompletionResult<ScanResponse>) -> Unit,
) {
scope.launch {
val derivations = collectDerivations(card)
if (derivations.isEmpty() || !card.settings.isHDWalletAllowed) {
callback(
CompletionResult.Success(
ScanResponse(
card = card,
productType = ProductType.Wallet,
walletData = session.environment.walletData,
primaryCard = primaryCard
)
)
)
return@launch
}
val derivations = collectDerivations(card)
if (derivations.isEmpty() || !card.settings.isHDWalletAllowed) {
callback(
CompletionResult.Success(
ScanResponse(
card = card,
productType = ProductType.Wallet,
walletData = session.environment.walletData,
primaryCard = primaryCard,
),
),
)
return
}
DeriveMultipleWalletPublicKeysTask(derivations).run(session) { result ->
when (result) {
is CompletionResult.Success -> {
val response = ScanResponse(
card = card,
productType = ProductType.Wallet,
walletData = session.environment.walletData,
derivedKeys = result.data.entries,
primaryCard = primaryCard
)
callback(CompletionResult.Success(response))
}
is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error))
DeriveMultipleWalletPublicKeysTask(derivations).run(session) { result ->
when (result) {
is CompletionResult.Success -> {
val response = ScanResponse(
card = card,
productType = ProductType.Wallet,
walletData = session.environment.walletData,
derivedKeys = result.data.entries,
primaryCard = primaryCard,
)
callback(CompletionResult.Success(response))
}
is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error))
}
}
}
private suspend fun getBlockchainsToDerive(card: Card): List<BlockchainNetwork> {
val currenciesRepository = currenciesRepository ?: return emptyList()
val cardCurrencies = currenciesRepository
.loadSavedCurrencies(card.cardId, card.settings.isHDWalletAllowed).toMutableList()
val blockchainsToDerive = cardCurrencies.ifEmpty {
private fun getBlockchainsToDerive(card: Card): List<BlockchainNetwork> {
val userTokensRepository = userTokensRepository ?: return emptyList()
val blockchainsToDerive = userTokensRepository.loadBlockchainsToDerive(card).toMutableList().ifEmpty {
mutableListOf(
BlockchainNetwork(Blockchain.Bitcoin, card),
BlockchainNetwork(Blockchain.Ethereum, card),
@ -236,7 +228,7 @@ private class ScanWalletProcessor(
listOf(
BlockchainNetwork(Blockchain.Ethereum, card),
BlockchainNetwork(Blockchain.EthereumTestnet, card),
)
),
)
}
if (additionalBlockchainsToDerive != null) {
@ -256,16 +248,14 @@ private class ScanWalletProcessor(
return blockchainsToDerive.distinct()
}
private suspend fun collectDerivations(card: Card): Map<ByteArrayKey, List<DerivationPath>> {
private fun collectDerivations(card: Card): Map<ByteArrayKey, List<DerivationPath>> {
val blockchains = getBlockchainsToDerive(card)
val derivations = mutableMapOf<ByteArrayKey, List<DerivationPath>>()
blockchains.forEach { blockchain ->
val curve = blockchain.blockchain.getPrimaryCurve()
val wallet = card.wallets.firstOrNull { it.curve == curve } ?: return@forEach
if (wallet.chainCode == null) return@forEach
val key = wallet.publicKey.toMapKey()
val path = blockchain.derivationPath?.let { DerivationPath(it) }
if (path != null) {