diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/visa/VisaCardActivationTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/visa/VisaCardActivationTask.kt index dd4e607371..3b07d873a0 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/visa/VisaCardActivationTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/visa/VisaCardActivationTask.kt @@ -14,12 +14,10 @@ import com.tangem.common.extensions.toHexString import com.tangem.common.map import com.tangem.common.timemeasure.RealtimeMonotonicTimeSource import com.tangem.core.error.ext.tangemError -import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey import com.tangem.datasource.local.visa.VisaAuthTokenStorage import com.tangem.datasource.local.visa.VisaOTPStorage import com.tangem.datasource.local.visa.VisaOtpData import com.tangem.datasource.local.visa.hasSavedOTP -import com.tangem.domain.common.visa.VisaUtilities import com.tangem.domain.common.visa.VisaWalletPublicKeyUtility import com.tangem.domain.models.scan.CardDTO import com.tangem.domain.visa.error.VisaActivationError @@ -29,7 +27,6 @@ import com.tangem.domain.visa.repository.VisaActivationRepository import com.tangem.domain.visa.repository.VisaAuthRepository import com.tangem.operations.GenerateOTPCommand import com.tangem.operations.attestation.AttestCardKeyCommand -import com.tangem.operations.derivation.DeriveWalletPublicKeyTask import com.tangem.operations.pins.SetUserCodeCommand import com.tangem.operations.sign.SignHashCommand import com.tangem.operations.sign.SignHashResponse @@ -95,23 +92,7 @@ class VisaCardActivationTask @AssistedInject constructor( context.signAuthorizationChallenge(mode.authorizationChallenge) } is VisaCardActivationTaskMode.SignOnly -> { - val wallet = - card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } - ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead()) - - val derivedPublicKey = when (val deriveKeyResult = context.deriveKey(wallet.publicKey)) { - is CompletionResult.Failure -> { - return CompletionResult.Failure(deriveKeyResult.error) - } - is CompletionResult.Success -> { - deriveKeyResult.data - } - } - - context.signData( - mode.dataToSignByCardWallet, - derivedPublicKey, - ) + context.signData(mode.dataToSignByCardWallet) } } } @@ -164,16 +145,7 @@ class VisaCardActivationTask @AssistedInject constructor( card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead()) - val derivedPublicKey = when (val deriveKeyResult = deriveKey(wallet.publicKey)) { - is CompletionResult.Failure -> { - return CompletionResult.Failure(deriveKeyResult.error) - } - is CompletionResult.Success -> { - deriveKeyResult.data - } - } - - val walletAddress = VisaWalletPublicKeyUtility.generateAddressOnSecp256k1(derivedPublicKey.publicKey) + val walletAddress = VisaWalletPublicKeyUtility.generateAddressOnSecp256k1(wallet.publicKey) .getOrElse { return CompletionResult.Failure(it.tangemError) } .value @@ -190,10 +162,7 @@ class VisaCardActivationTask @AssistedInject constructor( otpTaskDeferred.await() - signData( - dataToSign = dataToSign, - derivedPublicKey = derivedPublicKey, - ) + signData(dataToSign = dataToSign) } } @@ -294,7 +263,6 @@ class VisaCardActivationTask @AssistedInject constructor( private suspend fun SessionContext.signData( dataToSign: VisaDataToSignByCardWallet, - derivedPublicKey: ExtendedPublicKey, ): CompletionResult { val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead()) @@ -306,7 +274,6 @@ class VisaCardActivationTask @AssistedInject constructor( val task = SignHashCommand( hash = dataToSign.hashToSign.hexToBytes(), walletPublicKey = wallet.publicKey, - derivationPath = VisaUtilities.visaDefaultDerivationPath, ) val timedResult = RealtimeMonotonicTimeSource.measureTimedValue { @@ -325,7 +292,7 @@ class VisaCardActivationTask @AssistedInject constructor( handleSignedData( dataToSign = dataToSign, response = result.data, - derivedPublicKey = derivedPublicKey, + walletPublicKey = wallet.publicKey, ) } is CompletionResult.Failure -> { @@ -335,23 +302,9 @@ class VisaCardActivationTask @AssistedInject constructor( } } - private suspend fun SessionContext.deriveKey(publicKey: ByteArray): CompletionResult { - val derivationPath = VisaUtilities.visaDefaultDerivationPath - ?: return CompletionResult.Failure(VisaActivationError.FailedToCreateAddress.tangemError) - - val derivationTask = DeriveWalletPublicKeyTask(publicKey, derivationPath) - val derivationTaskResult = suspendCancellableCoroutine { continuation -> - derivationTask.run(session) { result -> - continuation.resume(result) - } - } - - return derivationTaskResult - } - private suspend fun SessionContext.handleSignedData( dataToSign: VisaDataToSignByCardWallet, - derivedPublicKey: ExtendedPublicKey, + walletPublicKey: ByteArray, response: SignHashResponse, ): CompletionResult { val otp = otpStorage.getOTP(cardId) ?: run { @@ -362,7 +315,7 @@ class VisaCardActivationTask @AssistedInject constructor( val rsvSignature = UnmarshalHelper.unmarshalSignatureExtended( signature = response.signature, hash = dataToSign.hashToSign.hexToBytes(), - publicKey = derivedPublicKey.publicKey.toDecompressedPublicKey(), + publicKey = walletPublicKey.toDecompressedPublicKey(), ).asRSVLegacyEVM().toHexString() val signedActivationData = dataToSign.sign( diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/visa/VisaCustomerWalletApproveTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/visa/VisaCustomerWalletApproveTask.kt index 55dd835a3e..232724142a 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/visa/VisaCustomerWalletApproveTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/visa/VisaCustomerWalletApproveTask.kt @@ -40,17 +40,12 @@ class VisaCustomerWalletApproveTask( } if (VisaUtilities.isVisaCard(card.firmwareVersion.doubleValue, card.batchId)) { - // TODO TVF-21 - callback(CompletionResult.Failure(TangemSdkError.Underlying("Can't use Visa card for approve"))) + callback(CompletionResult.Failure(VisaActivationError.VisaCardForApproval.tangemError)) return } if (visaDataForApprove.customerWalletCardId != null && card.cardId != visaDataForApprove.customerWalletCardId) { - callback( - CompletionResult.Failure( - TangemSdkError.Underlying("Use tangem wallet specified during visa registration"), // TODO TVF-21 - ), - ) + callback(CompletionResult.Failure(VisaActivationError.CardIdNotMatched.tangemError)) return } diff --git a/app/src/main/java/com/tangem/tap/domain/visa/VisaCardScanHandler.kt b/app/src/main/java/com/tangem/tap/domain/visa/VisaCardScanHandler.kt index b83d23f8d9..e31948a49c 100644 --- a/app/src/main/java/com/tangem/tap/domain/visa/VisaCardScanHandler.kt +++ b/app/src/main/java/com/tangem/tap/domain/visa/VisaCardScanHandler.kt @@ -2,17 +2,13 @@ package com.tangem.tap.domain.visa import arrow.core.getOrElse import com.tangem.common.CompletionResult -import com.tangem.common.card.CardWallet import com.tangem.common.card.EllipticCurve import com.tangem.common.core.CardSession import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.hexToBytes import com.tangem.common.extensions.toHexString import com.tangem.core.error.ext.tangemError -import com.tangem.crypto.hdWallet.DerivationPath -import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey import com.tangem.datasource.local.visa.VisaAuthTokenStorage -import com.tangem.domain.common.visa.VisaUtilities import com.tangem.domain.common.visa.VisaWalletPublicKeyUtility import com.tangem.domain.visa.error.VisaActivationError import com.tangem.domain.visa.error.VisaAuthorizationAPIError @@ -22,7 +18,6 @@ import com.tangem.domain.visa.repository.VisaActivationRepository import com.tangem.domain.visa.repository.VisaAuthRepository import com.tangem.operations.attestation.AttestCardKeyCommand import com.tangem.operations.attestation.AttestCardKeyResponse -import com.tangem.operations.derivation.DeriveWalletPublicKeyTask import com.tangem.operations.sign.SignHashCommand import com.tangem.operations.sign.SignHashResponse import kotlinx.coroutines.suspendCancellableCoroutine @@ -61,54 +56,19 @@ internal class VisaCardScanHandler @Inject constructor( session = session, ) - val wallet = card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: run { + card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: run { val activationInput = VisaActivationInput(card.cardId, card.cardPublicKey.toHexString(), card.isAccessCodeSet) val activationStatus = VisaCardActivationStatus.NotStartedActivation(activationInput) return CompletionResult.Success(activationStatus) } - return context.deriveKey(wallet) - } - - private suspend fun SessionContext.deriveKey(wallet: CardWallet): CompletionResult { - val derivationPath = VisaUtilities.visaDefaultDerivationPath ?: run { - Timber.e("Failed to create derivation path while first scan") - - return CompletionResult.Failure(VisaCardScanError.FailedToCreateDerivationPath.tangemError) - } - - val derivationTask = DeriveWalletPublicKeyTask(wallet.publicKey, derivationPath) - val derivationTaskResult = suspendCancellableCoroutine { continuation -> - derivationTask.run(session) { result -> - continuation.resume(result) - } - } - return handleDerivationResponse(derivationTaskResult) - } - - private suspend fun SessionContext.handleDerivationResponse( - result: CompletionResult, - ): CompletionResult { - return when (result) { - is CompletionResult.Success -> { - Timber.i("Start task for loading challenge for Visa wallet") - handleWalletAuthorization() - } - is CompletionResult.Failure -> { - CompletionResult.Failure(result.error) - } - } + return context.handleWalletAuthorization() } private suspend fun SessionContext.handleWalletAuthorization(): CompletionResult { Timber.i("Started handling authorization using Visa wallet") - val derivationPath = VisaUtilities.visaDefaultDerivationPath ?: run { - Timber.e("Failed to create derivation path while handling wallet authorization") - return CompletionResult.Failure(VisaCardScanError.FailedToCreateDerivationPath.tangemError) - } - val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead()) val wallet = card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: run { @@ -116,12 +76,7 @@ internal class VisaCardScanHandler @Inject constructor( return CompletionResult.Failure(VisaCardScanError.FailedToFindWallet.tangemError) } - val extendedPublicKey = wallet.derivedKeys[derivationPath] ?: run { - Timber.e("Failed to find extended public key while handling wallet authorization") - return CompletionResult.Failure(VisaCardScanError.FailedToFindDerivedWalletKey.tangemError) - } - - val walletAddress = VisaWalletPublicKeyUtility.generateAddressOnSecp256k1(extendedPublicKey.publicKey) + val walletAddress = VisaWalletPublicKeyUtility.generateAddressOnSecp256k1(wallet.publicKey) .getOrElse { return CompletionResult.Failure(it.tangemError) } @@ -132,9 +87,7 @@ internal class VisaCardScanHandler @Inject constructor( error("sign and get specific error to switch to card_id flow") visaAuthRepository.getCardWalletAuthChallenge(cardWalletAddress = walletAddress.value) }.getOrElse { - Timber.i( - "Failed to get Access token for Wallet public key authoziation. Authorizing using Card Pub key", - ) + Timber.i("Failed to get Access token for Wallet public key authorization. Authorizing using Card Pub key") return handleCardAuthorization( cardWalletAddress = walletAddress.value, ) @@ -142,7 +95,6 @@ internal class VisaCardScanHandler @Inject constructor( val signChallengeResult = signChallengeWithWallet( publicKey = wallet.publicKey, - derivationPath = derivationPath, nonce = challengeResponse.challenge, ) @@ -169,9 +121,7 @@ internal class VisaCardScanHandler @Inject constructor( val authorizationTokensResponse = runCatching { visaAuthRepository.getAccessTokens(signedChallenge = signedChallenge) }.getOrElse { - Timber.i( - "Failed to get Access token for Wallet public key authoziation. Authorizing using Card Pub key", - ) + Timber.i("Failed to get Access token for Wallet public key authorization. Authorizing using Card Pub key") return handleCardAuthorization( cardWalletAddress = cardWalletAddress, ) @@ -271,13 +221,11 @@ internal class VisaCardScanHandler @Inject constructor( private suspend fun SessionContext.signChallengeWithWallet( publicKey: ByteArray, - derivationPath: DerivationPath, nonce: String, ): CompletionResult { val signHashCommand = SignHashCommand( hash = nonce.hexToBytes(), walletPublicKey = publicKey, - derivationPath = derivationPath, ) return suspendCancellableCoroutine { signHashCommand.run(session) { result -> diff --git a/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/error/VisaError.kt b/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/error/VisaError.kt index bf9bd888dd..6ddfd6c0d7 100644 --- a/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/error/VisaError.kt +++ b/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/error/VisaError.kt @@ -45,6 +45,8 @@ enum class VisaActivationError( AddressNotMatched(104003008), InconsistentRemoteState(104003009), FailedRemoteState(104003010), + VisaCardForApproval(104003011), + CardIdNotMatched(104003011), } object VisaAuthorizationAPIError : UniversalError {