Updated on 2026-08-14
This commit is contained in:
parent
ed26d23a78
commit
f3192b6d27
23 changed files with 413 additions and 46 deletions
|
|
@ -10,6 +10,7 @@ import com.tangem.sdk.api.TangemSdkManager
|
|||
import com.tangem.tap.domain.sdk.impl.DefaultTangemSdkManager
|
||||
import com.tangem.tap.domain.sdk.impl.MockTangemSdkManager
|
||||
import com.tangem.tap.domain.tasks.visa.TangemPayGenerateAddressAndSignChallengeTask
|
||||
import com.tangem.tap.domain.tasks.visa.TangemPayGenerateVirtualAccountAddressTask
|
||||
import com.tangem.tap.domain.tasks.visa.VisaCardActivationTask
|
||||
import com.tangem.tap.domain.visa.VisaCardScanHandler
|
||||
import dagger.Module
|
||||
|
|
@ -31,6 +32,7 @@ internal class TangemSdkManagerModule {
|
|||
visaCardScanHandler: VisaCardScanHandler,
|
||||
visaCardActivationTaskFactory: VisaCardActivationTask.Factory,
|
||||
tangemPayChallengeTaskFactory: TangemPayGenerateAddressAndSignChallengeTask.Factory,
|
||||
tangemPayVirtualAccountTaskFactory: TangemPayGenerateVirtualAccountAddressTask.Factory,
|
||||
onboardingV2FeatureToggles: OnboardingV2FeatureToggles,
|
||||
analyticsErrorHandler: AnalyticsErrorHandler,
|
||||
cardRepository: CardRepository,
|
||||
|
|
@ -44,6 +46,7 @@ internal class TangemSdkManagerModule {
|
|||
visaCardScanHandler = visaCardScanHandler,
|
||||
visaCardActivationTaskFactory = visaCardActivationTaskFactory,
|
||||
tangemPayChallengeTaskFactory = tangemPayChallengeTaskFactory,
|
||||
tangemPayVirtualAccountTaskFactory = tangemPayVirtualAccountTaskFactory,
|
||||
onboardingV2FeatureToggles = onboardingV2FeatureToggles,
|
||||
analyticsErrorHandler = analyticsErrorHandler,
|
||||
cardRepository = cardRepository,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import com.tangem.tap.common.analytics.events.TangemSdkErrorEvent
|
|||
import com.tangem.tap.common.analytics.paramsInterceptor.CardContextInterceptor
|
||||
import com.tangem.tap.domain.tasks.product.*
|
||||
import com.tangem.tap.domain.tasks.visa.TangemPayGenerateAddressAndSignChallengeTask
|
||||
import com.tangem.tap.domain.tasks.visa.TangemPayGenerateVirtualAccountAddressTask
|
||||
import com.tangem.tap.domain.tasks.visa.TangemPaySignWithdrawalHashTask
|
||||
import com.tangem.tap.domain.tasks.visa.VisaCardActivationTask
|
||||
import com.tangem.tap.domain.tasks.visa.VisaCustomerWalletApproveTask
|
||||
|
|
@ -72,6 +73,7 @@ internal class DefaultTangemSdkManager(
|
|||
private val visaCardScanHandler: VisaCardScanHandler,
|
||||
private val visaCardActivationTaskFactory: VisaCardActivationTask.Factory,
|
||||
private val tangemPayChallengeTaskFactory: TangemPayGenerateAddressAndSignChallengeTask.Factory,
|
||||
private val tangemPayVirtualAccountTaskFactory: TangemPayGenerateVirtualAccountAddressTask.Factory,
|
||||
private val onboardingV2FeatureToggles: OnboardingV2FeatureToggles,
|
||||
private val analyticsErrorHandler: AnalyticsErrorHandler,
|
||||
private val cardRepository: CardRepository,
|
||||
|
|
@ -531,6 +533,24 @@ internal class DefaultTangemSdkManager(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun tangemPayProduceVirtualAccountData(
|
||||
preflightReadFilter: PreflightReadFilter,
|
||||
): Either<Throwable, VirtualAccountActivationData> {
|
||||
return coroutineScope {
|
||||
val result = runTaskAsyncReturnOnMain(
|
||||
runnable = tangemPayVirtualAccountTaskFactory.create(coroutineScope = this),
|
||||
cardId = null,
|
||||
initialMessage = Message(resources.getStringSafe(R.string.initial_message_tap_header)),
|
||||
preflightReadFilter = preflightReadFilter,
|
||||
)
|
||||
|
||||
return@coroutineScope when (result) {
|
||||
is CompletionResult.Failure<*> -> result.error.left()
|
||||
is CompletionResult.Success<VirtualAccountActivationData> -> result.data.right()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getWithdrawalSignature(
|
||||
hash: String,
|
||||
preflightReadFilter: PreflightReadFilter,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.tangem.domain.models.scan.ScanResponse
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.pay.WithdrawalSignatureResult
|
||||
import com.tangem.domain.visa.model.TangemPayInitialCredentials
|
||||
import com.tangem.domain.visa.model.VirtualAccountActivationData
|
||||
import com.tangem.domain.visa.model.VisaActivationInput
|
||||
import com.tangem.domain.visa.model.VisaDataForApprove
|
||||
import com.tangem.domain.visa.model.VisaSignedDataByCustomerWallet
|
||||
|
|
@ -241,6 +242,12 @@ class MockTangemSdkManager(
|
|||
error("Not implemented")
|
||||
}
|
||||
|
||||
override suspend fun tangemPayProduceVirtualAccountData(
|
||||
preflightReadFilter: PreflightReadFilter,
|
||||
): Either<Throwable, VirtualAccountActivationData> {
|
||||
error("Not implemented")
|
||||
}
|
||||
|
||||
override suspend fun getWithdrawalSignature(
|
||||
hash: String,
|
||||
preflightReadFilter: PreflightReadFilter,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
package com.tangem.tap.domain.tasks.visa
|
||||
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.card.CardWallet
|
||||
import com.tangem.common.core.CardSession
|
||||
import com.tangem.common.core.CardSessionRunnable
|
||||
import com.tangem.common.core.CompletionCallback
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.extensions.toMapKey
|
||||
import com.tangem.core.error.ext.tangemError
|
||||
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
|
||||
import com.tangem.domain.card.common.visa.VisaUtilities
|
||||
import com.tangem.domain.visa.error.VisaActivationError
|
||||
import com.tangem.domain.visa.model.VirtualAccountActivationData
|
||||
import com.tangem.operations.derivation.DeriveWalletPublicKeyTask
|
||||
import com.tangem.operations.derivation.ExtendedPublicKeysMap
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* Derives the Virtual Account key ([VisaUtilities.virtualAccountDerivationPath]) on the card and
|
||||
* generates its deposit address. The derived key is returned (keyed by the seed wallet public key)
|
||||
* so the caller can persist it via `DerivationsRepository.storeDerivedKeys` — no second tap needed.
|
||||
*/
|
||||
class TangemPayGenerateVirtualAccountAddressTask @AssistedInject constructor(
|
||||
@Assisted private val coroutineScope: CoroutineScope,
|
||||
) : CardSessionRunnable<VirtualAccountActivationData> {
|
||||
|
||||
override fun run(session: CardSession, callback: CompletionCallback<VirtualAccountActivationData>) {
|
||||
coroutineScope.launch {
|
||||
callback(runSuspend(session = session))
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun runSuspend(session: CardSession): CompletionResult<VirtualAccountActivationData> {
|
||||
val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||
val wallet = card.wallets.firstOrNull { it.curve == VisaUtilities.curve }
|
||||
?: return CompletionResult.Failure(VisaActivationError.MissingWallet.tangemError)
|
||||
|
||||
val extendedPublicKey = when (val derivationResult = runDerivationTask(session, wallet)) {
|
||||
is CompletionResult.Failure<*> -> return CompletionResult.Failure(derivationResult.error)
|
||||
is CompletionResult.Success<ExtendedPublicKey> -> derivationResult.data
|
||||
}
|
||||
|
||||
val address = VisaUtilities.generateAddressFromExtendedKey(extendedPublicKey = extendedPublicKey)
|
||||
|
||||
val derivedKeys = mapOf(
|
||||
wallet.publicKey.toMapKey() to ExtendedPublicKeysMap(
|
||||
mapOf(VisaUtilities.virtualAccountDerivationPath to extendedPublicKey),
|
||||
),
|
||||
)
|
||||
|
||||
return CompletionResult.Success(
|
||||
data = VirtualAccountActivationData(address = address, derivedKeys = derivedKeys),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun runDerivationTask(
|
||||
session: CardSession,
|
||||
wallet: CardWallet,
|
||||
): CompletionResult<ExtendedPublicKey> {
|
||||
val deferred = CompletableDeferred<CompletionResult<ExtendedPublicKey>>()
|
||||
val derivationTask = DeriveWalletPublicKeyTask(
|
||||
walletPublicKey = wallet.publicKey,
|
||||
derivationPath = VisaUtilities.virtualAccountDerivationPath,
|
||||
)
|
||||
|
||||
derivationTask.run(session = session, callback = deferred::complete)
|
||||
return deferred.await()
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(coroutineScope: CoroutineScope): TangemPayGenerateVirtualAccountAddressTask
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue