Updated on 2026-08-14
This commit is contained in:
parent
ded577faff
commit
aea7f5f415
21 changed files with 220 additions and 136 deletions
|
|
@ -9,11 +9,13 @@ import com.tangem.common.card.EllipticCurve
|
|||
import com.tangem.common.core.CardSession
|
||||
import com.tangem.common.core.CardSessionRunnable
|
||||
import com.tangem.common.core.CompletionCallback
|
||||
import com.tangem.common.core.TangemError
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
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.CryptoUtils
|
||||
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
||||
import com.tangem.datasource.local.visa.VisaOTPStorage
|
||||
|
|
@ -22,6 +24,8 @@ 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
|
||||
import com.tangem.domain.visa.error.VisaAuthorizationAPIError
|
||||
import com.tangem.domain.visa.model.*
|
||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||
import com.tangem.domain.visa.repository.VisaAuthRepository
|
||||
|
|
@ -68,7 +72,7 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||
|
||||
if (card.cardId != activationInput.cardId) {
|
||||
return CompletionResult.Failure(TangemSdkError.Underlying(VisaActivationError.WrongCard.message))
|
||||
return CompletionResult.Failure(VisaActivationError.WrongCard.tangemError)
|
||||
}
|
||||
|
||||
val visaActivationRepository = visaActivationRepositoryFactory.create(
|
||||
|
|
@ -149,7 +153,7 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
|
||||
private suspend fun SessionContext.getDataToSign(
|
||||
signedChallenge: VisaAuthSignedChallenge,
|
||||
): Either<TangemSdkError.Underlying, VisaDataToSignByCardWallet> = either {
|
||||
): Either<TangemError, VisaDataToSignByCardWallet> = either {
|
||||
catch(
|
||||
block = {
|
||||
val tokens = visaAuthRepository.getAccessTokens(signedChallenge)
|
||||
|
|
@ -158,13 +162,13 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
|
||||
val remoteState = visaActivationRepository.getActivationRemoteState()
|
||||
if (remoteState !is VisaActivationRemoteState.CardWalletSignatureRequired) {
|
||||
raise(TangemSdkError.Underlying(VisaActivationError.WrongRemoteState.message))
|
||||
raise(VisaActivationError.WrongRemoteState.tangemError)
|
||||
}
|
||||
|
||||
visaActivationRepository.getCardWalletAcceptanceData(remoteState.request)
|
||||
},
|
||||
catch = {
|
||||
raise(TangemSdkError.Underlying("Underlying network error: ${it.message ?: ""}"))
|
||||
raise(VisaAuthorizationAPIError.tangemError)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -246,10 +250,10 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||
|
||||
val derivedPublicKey = wallet.derivedKeys[VisaUtilities.visaDefaultDerivationPath]
|
||||
?: return CompletionResult.Failure(TangemSdkError.Underlying(VisaActivationError.MissingWallet.message))
|
||||
?: return CompletionResult.Failure(VisaActivationError.MissingWallet.tangemError)
|
||||
|
||||
val walletAddress = VisaWalletPublicKeyUtility.generateAddressOnSecp256k1(derivedPublicKey.publicKey)
|
||||
.getOrElse { return CompletionResult.Failure(TangemSdkError.Underlying(it.message)) }
|
||||
.getOrElse { return CompletionResult.Failure(it.tangemError) }
|
||||
.value
|
||||
|
||||
val task = SignHashCommand(
|
||||
|
|
@ -291,7 +295,7 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
): CompletionResult<VisaCardActivationResponse> {
|
||||
val otp = otpStorage.getOTP(cardId) ?: run {
|
||||
createOTP()
|
||||
otpStorage.getOTP(cardId) ?: return CompletionResult.Failure(TangemSdkError.Underlying("OTP not found"))
|
||||
otpStorage.getOTP(cardId) ?: return CompletionResult.Failure(VisaActivationError.MissingRootOTP.tangemError)
|
||||
}
|
||||
|
||||
val signedActivationData = dataToSign.sign(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.common.core.CompletionCallback
|
|||
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.domain.common.util.derivationStyleProvider
|
||||
|
|
@ -18,7 +19,7 @@ import com.tangem.domain.common.visa.VisaUtilities
|
|||
import com.tangem.domain.common.visa.VisaWalletPublicKeyUtility
|
||||
import com.tangem.domain.common.visa.VisaWalletPublicKeyUtility.findKeyWithoutDerivation
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.visa.model.VisaActivationError
|
||||
import com.tangem.domain.visa.error.VisaActivationError
|
||||
import com.tangem.domain.visa.model.VisaDataForApprove
|
||||
import com.tangem.domain.visa.model.VisaSignedDataByCustomerWallet
|
||||
import com.tangem.domain.visa.model.sign
|
||||
|
|
@ -37,6 +38,7 @@ 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")))
|
||||
return
|
||||
}
|
||||
|
|
@ -44,7 +46,7 @@ class VisaCustomerWalletApproveTask(
|
|||
if (visaDataForApprove.customerWalletCardId != null && card.cardId != visaDataForApprove.customerWalletCardId) {
|
||||
callback(
|
||||
CompletionResult.Failure(
|
||||
TangemSdkError.Underlying("Use tangem wallet specified during visa registration"),
|
||||
TangemSdkError.Underlying("Use tangem wallet specified during visa registration"), // TODO TVF-21
|
||||
),
|
||||
)
|
||||
return
|
||||
|
|
@ -74,16 +76,12 @@ class VisaCustomerWalletApproveTask(
|
|||
}
|
||||
|
||||
val derivationPath = VisaUtilities.visaDefaultDerivationPath(derivationStyle) ?: run {
|
||||
callback(
|
||||
CompletionResult.Failure(
|
||||
TangemSdkError.Underlying("Failed to generate derivation path with provided derivation style"),
|
||||
),
|
||||
)
|
||||
callback(CompletionResult.Failure(VisaActivationError.FailedToCreateAddress.tangemError))
|
||||
return
|
||||
}
|
||||
|
||||
val wallet = card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: run {
|
||||
callback(CompletionResult.Failure(TangemSdkError.Underlying(VisaActivationError.MissingWallet.message)))
|
||||
callback(CompletionResult.Failure(VisaActivationError.MissingWallet.tangemError))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +121,7 @@ class VisaCustomerWalletApproveTask(
|
|||
)
|
||||
|
||||
validationResult.onLeft {
|
||||
callback(CompletionResult.Failure(TangemSdkError.Underlying(it.message)))
|
||||
callback(CompletionResult.Failure(it.tangemError))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +142,7 @@ class VisaCustomerWalletApproveTask(
|
|||
targetAddress = visaDataForApprove.targetAddress,
|
||||
card = CardDTO(card),
|
||||
).getOrElse {
|
||||
callback(CompletionResult.Failure(TangemSdkError.Underlying(it.message)))
|
||||
callback(CompletionResult.Failure(it.tangemError))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,15 @@ 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
|
||||
import com.tangem.domain.visa.error.VisaCardScanError
|
||||
import com.tangem.domain.visa.model.*
|
||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||
import com.tangem.domain.visa.repository.VisaAuthRepository
|
||||
|
|
@ -71,9 +75,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
val derivationPath = VisaUtilities.visaDefaultDerivationPath ?: run {
|
||||
Timber.e("Failed to create derivation path while first scan")
|
||||
|
||||
return CompletionResult.Failure(
|
||||
TangemSdkError.Underlying(VisaCardScanHandlerError.FailedToCreateDerivationPath.errorDescription),
|
||||
)
|
||||
return CompletionResult.Failure(VisaCardScanError.FailedToCreateDerivationPath.tangemError)
|
||||
}
|
||||
|
||||
val derivationTask = DeriveWalletPublicKeyTask(wallet.publicKey, derivationPath)
|
||||
|
|
@ -104,32 +106,24 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
|
||||
val derivationPath = VisaUtilities.visaDefaultDerivationPath ?: run {
|
||||
Timber.e("Failed to create derivation path while handling wallet authorization")
|
||||
return CompletionResult.Failure(
|
||||
TangemSdkError.Underlying(VisaCardScanHandlerError.FailedToCreateDerivationPath.errorDescription),
|
||||
)
|
||||
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 {
|
||||
Timber.e("Failed to find extended public key while handling wallet authorization")
|
||||
return CompletionResult.Failure(
|
||||
TangemSdkError.Underlying(VisaCardScanHandlerError.FailedToFindDerivedWalletKey.errorDescription),
|
||||
)
|
||||
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(
|
||||
TangemSdkError.Underlying(VisaCardScanHandlerError.FailedToFindDerivedWalletKey.errorDescription),
|
||||
)
|
||||
return CompletionResult.Failure(VisaCardScanError.FailedToFindDerivedWalletKey.tangemError)
|
||||
}
|
||||
|
||||
val walletAddress = VisaWalletPublicKeyUtility.generateAddressOnSecp256k1(extendedPublicKey.publicKey)
|
||||
.getOrElse {
|
||||
return CompletionResult.Failure(
|
||||
TangemSdkError.Underlying("Cannot generate address on Visa curve"),
|
||||
)
|
||||
return CompletionResult.Failure(it.tangemError)
|
||||
}
|
||||
|
||||
Timber.i("Requesting challenge for wallet authorization")
|
||||
|
|
@ -200,7 +194,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
)
|
||||
}.getOrElse {
|
||||
Timber.e("Failed to get challenge for Card authorization. Plain error: ${it.message}")
|
||||
return CompletionResult.Failure(TangemSdkError.Underlying(it.message ?: "Unknown error"))
|
||||
return CompletionResult.Failure(VisaAuthorizationAPIError.tangemError)
|
||||
}
|
||||
|
||||
Timber.i("Received challenge to sign: ${challengeResponse.challenge}")
|
||||
|
|
@ -230,11 +224,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
)
|
||||
}.getOrElse {
|
||||
Timber.e("Failed to sign challenge with Card public key. Plain error: ${it.message}")
|
||||
return CompletionResult.Failure(
|
||||
TangemSdkError.Underlying(
|
||||
customMessage = it.message ?: "Unknown error",
|
||||
),
|
||||
)
|
||||
return CompletionResult.Failure(VisaAuthorizationAPIError.tangemError)
|
||||
}
|
||||
|
||||
visaAuthTokenStorage.store(
|
||||
|
|
@ -251,7 +241,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
}
|
||||
|
||||
if (error != null) {
|
||||
return CompletionResult.Failure(TangemSdkError.Underlying(error.message))
|
||||
return CompletionResult.Failure(error.tangemError)
|
||||
}
|
||||
|
||||
val activationInput = VisaActivationInput(
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
package com.tangem.tap.domain.visa
|
||||
|
||||
private const val COMMON_DESCRIPTION = "Error occurred. Please contact support."
|
||||
|
||||
internal enum class VisaCardScanHandlerError(val errorDescription: String) {
|
||||
FailedToCreateDerivationPath(COMMON_DESCRIPTION),
|
||||
FailedToFindWallet(COMMON_DESCRIPTION),
|
||||
FailedToFindDerivedWalletKey(COMMON_DESCRIPTION),
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue