Updated on 2026-08-14

This commit is contained in:
Tangem 2026-04-08 14:09:57 +03:00
parent 52a607c1f5
commit 9944036c4d
29 changed files with 874 additions and 60 deletions

View file

@ -29,6 +29,9 @@ interface DerivationsRepository {
derivations: Map<ByteArrayKey, List<DerivationPath>>,
): Map<ByteArrayKey, ExtendedPublicKeysMap>
/** Returns already derived extended public keys for the given [seedKey] */
suspend fun getExistingDerivedKeys(userWalletId: UserWalletId, seedKey: ByteArrayKey): ExtendedPublicKeysMap
/** Check if user [userWalletId] has missed derivations using map of [Network.ID] with extraDerivationPath */
suspend fun hasMissedDerivations(
userWalletId: UserWalletId,

View file

@ -1,7 +1,6 @@
package com.tangem.domain.wallets.usecase
import arrow.core.Either
import arrow.core.right
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.utils.toBlockchain
import com.tangem.common.extensions.ByteArrayKey
@ -38,23 +37,37 @@ class GetExtendedPublicKeyForCurrencyUseCase(
error("No derivation found")
}
val seedKey = walletManager.wallet.publicKey.seedKey
val existingKeys = derivationsRepository.getExistingDerivedKeys(
userWalletId = userWalletId,
seedKey = ByteArrayKey(seedKey),
)
var childKey = makeChildKey(
isBip44DerivationStyleXPUB = blockchain.isBip44DerivationStyleXPUB(),
extendedPublicKey = hdKey.extendedPublicKey,
derivationPath = hdKey.path,
)
// Fill from already derived keys if available
if (childKey.extendedPublicKey == null) {
existingKeys[childKey.derivationPath]?.let {
childKey = childKey.copy(extendedPublicKey = it)
}
}
val parentPath = childKey.derivationPath.dropLastNodes(1)
var parentKey = Key(
derivationPath = childKey.derivationPath.dropLastNodes(1),
extendedPublicKey = null,
derivationPath = parentPath,
extendedPublicKey = existingKeys[parentPath],
)
val pendingDerivations = getPendingDerivations(childKey, parentKey)
val derivedKeys = deriveKeys(
userWalletId = userWalletId,
seedKey = walletManager.wallet.publicKey.seedKey,
paths = pendingDerivations,
)
val derivedKeys = if (pendingDerivations.isNotEmpty()) {
deriveKeys(userWalletId = userWalletId, seedKey = seedKey, paths = pendingDerivations)
} else {
ExtendedPublicKeysMap(emptyMap())
}
if (childKey.extendedPublicKey == null) {
childKey = childKey.copy(
@ -72,22 +85,6 @@ class GetExtendedPublicKeyForCurrencyUseCase(
}
}
/**
* @return true if xpub generation is supported, false otherwise
*/
suspend fun isSupported(userWalletId: UserWalletId, network: Network): Either<Throwable, Boolean> = Either.catch {
val walletManager = walletManagersFacade.getOrCreateWalletManager(userWalletId, network)
?: error("Wallet not found for user wallet $userWalletId and network ${network.id}")
val blockchain = network.toBlockchain()
val isSecp256k1Blockchain = Blockchain.secp256k1Blockchains(network.isTestnet).contains(blockchain)
val isHdKey = walletManager.wallet.publicKey.derivationType?.hdKey
val isSupported = isSecp256k1Blockchain && isHdKey != null
return isSupported.right()
}
private suspend fun deriveKeys(
userWalletId: UserWalletId,
seedKey: ByteArray,