Updated on 2026-08-14
This commit is contained in:
parent
ded577faff
commit
aea7f5f415
21 changed files with 220 additions and 136 deletions
|
|
@ -122,6 +122,7 @@ dependencies {
|
||||||
implementation(projects.core.utils)
|
implementation(projects.core.utils)
|
||||||
implementation(projects.core.decompose)
|
implementation(projects.core.decompose)
|
||||||
implementation(projects.core.deepLinks)
|
implementation(projects.core.deepLinks)
|
||||||
|
implementation(projects.core.error.ext)
|
||||||
implementation(projects.libs.crypto)
|
implementation(projects.libs.crypto)
|
||||||
implementation(projects.libs.auth)
|
implementation(projects.libs.auth)
|
||||||
implementation(projects.libs.blockchainSdk)
|
implementation(projects.libs.blockchainSdk)
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,13 @@ import com.tangem.common.card.EllipticCurve
|
||||||
import com.tangem.common.core.CardSession
|
import com.tangem.common.core.CardSession
|
||||||
import com.tangem.common.core.CardSessionRunnable
|
import com.tangem.common.core.CardSessionRunnable
|
||||||
import com.tangem.common.core.CompletionCallback
|
import com.tangem.common.core.CompletionCallback
|
||||||
|
import com.tangem.common.core.TangemError
|
||||||
import com.tangem.common.core.TangemSdkError
|
import com.tangem.common.core.TangemSdkError
|
||||||
import com.tangem.common.extensions.hexToBytes
|
import com.tangem.common.extensions.hexToBytes
|
||||||
import com.tangem.common.extensions.toHexString
|
import com.tangem.common.extensions.toHexString
|
||||||
import com.tangem.common.map
|
import com.tangem.common.map
|
||||||
import com.tangem.common.timemeasure.RealtimeMonotonicTimeSource
|
import com.tangem.common.timemeasure.RealtimeMonotonicTimeSource
|
||||||
|
import com.tangem.core.error.ext.tangemError
|
||||||
import com.tangem.crypto.CryptoUtils
|
import com.tangem.crypto.CryptoUtils
|
||||||
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
||||||
import com.tangem.datasource.local.visa.VisaOTPStorage
|
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.VisaUtilities
|
||||||
import com.tangem.domain.common.visa.VisaWalletPublicKeyUtility
|
import com.tangem.domain.common.visa.VisaWalletPublicKeyUtility
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
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.model.*
|
||||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||||
import com.tangem.domain.visa.repository.VisaAuthRepository
|
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())
|
val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||||
|
|
||||||
if (card.cardId != activationInput.cardId) {
|
if (card.cardId != activationInput.cardId) {
|
||||||
return CompletionResult.Failure(TangemSdkError.Underlying(VisaActivationError.WrongCard.message))
|
return CompletionResult.Failure(VisaActivationError.WrongCard.tangemError)
|
||||||
}
|
}
|
||||||
|
|
||||||
val visaActivationRepository = visaActivationRepositoryFactory.create(
|
val visaActivationRepository = visaActivationRepositoryFactory.create(
|
||||||
|
|
@ -149,7 +153,7 @@ class VisaCardActivationTask @AssistedInject constructor(
|
||||||
|
|
||||||
private suspend fun SessionContext.getDataToSign(
|
private suspend fun SessionContext.getDataToSign(
|
||||||
signedChallenge: VisaAuthSignedChallenge,
|
signedChallenge: VisaAuthSignedChallenge,
|
||||||
): Either<TangemSdkError.Underlying, VisaDataToSignByCardWallet> = either {
|
): Either<TangemError, VisaDataToSignByCardWallet> = either {
|
||||||
catch(
|
catch(
|
||||||
block = {
|
block = {
|
||||||
val tokens = visaAuthRepository.getAccessTokens(signedChallenge)
|
val tokens = visaAuthRepository.getAccessTokens(signedChallenge)
|
||||||
|
|
@ -158,13 +162,13 @@ class VisaCardActivationTask @AssistedInject constructor(
|
||||||
|
|
||||||
val remoteState = visaActivationRepository.getActivationRemoteState()
|
val remoteState = visaActivationRepository.getActivationRemoteState()
|
||||||
if (remoteState !is VisaActivationRemoteState.CardWalletSignatureRequired) {
|
if (remoteState !is VisaActivationRemoteState.CardWalletSignatureRequired) {
|
||||||
raise(TangemSdkError.Underlying(VisaActivationError.WrongRemoteState.message))
|
raise(VisaActivationError.WrongRemoteState.tangemError)
|
||||||
}
|
}
|
||||||
|
|
||||||
visaActivationRepository.getCardWalletAcceptanceData(remoteState.request)
|
visaActivationRepository.getCardWalletAcceptanceData(remoteState.request)
|
||||||
},
|
},
|
||||||
catch = {
|
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())
|
?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||||
|
|
||||||
val derivedPublicKey = wallet.derivedKeys[VisaUtilities.visaDefaultDerivationPath]
|
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)
|
val walletAddress = VisaWalletPublicKeyUtility.generateAddressOnSecp256k1(derivedPublicKey.publicKey)
|
||||||
.getOrElse { return CompletionResult.Failure(TangemSdkError.Underlying(it.message)) }
|
.getOrElse { return CompletionResult.Failure(it.tangemError) }
|
||||||
.value
|
.value
|
||||||
|
|
||||||
val task = SignHashCommand(
|
val task = SignHashCommand(
|
||||||
|
|
@ -291,7 +295,7 @@ class VisaCardActivationTask @AssistedInject constructor(
|
||||||
): CompletionResult<VisaCardActivationResponse> {
|
): CompletionResult<VisaCardActivationResponse> {
|
||||||
val otp = otpStorage.getOTP(cardId) ?: run {
|
val otp = otpStorage.getOTP(cardId) ?: run {
|
||||||
createOTP()
|
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(
|
val signedActivationData = dataToSign.sign(
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import com.tangem.common.core.CompletionCallback
|
||||||
import com.tangem.common.core.TangemSdkError
|
import com.tangem.common.core.TangemSdkError
|
||||||
import com.tangem.common.extensions.hexToBytes
|
import com.tangem.common.extensions.hexToBytes
|
||||||
import com.tangem.common.extensions.toHexString
|
import com.tangem.common.extensions.toHexString
|
||||||
|
import com.tangem.core.error.ext.tangemError
|
||||||
import com.tangem.crypto.hdWallet.DerivationPath
|
import com.tangem.crypto.hdWallet.DerivationPath
|
||||||
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
|
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
|
||||||
import com.tangem.domain.common.util.derivationStyleProvider
|
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
|
||||||
import com.tangem.domain.common.visa.VisaWalletPublicKeyUtility.findKeyWithoutDerivation
|
import com.tangem.domain.common.visa.VisaWalletPublicKeyUtility.findKeyWithoutDerivation
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
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.VisaDataForApprove
|
||||||
import com.tangem.domain.visa.model.VisaSignedDataByCustomerWallet
|
import com.tangem.domain.visa.model.VisaSignedDataByCustomerWallet
|
||||||
import com.tangem.domain.visa.model.sign
|
import com.tangem.domain.visa.model.sign
|
||||||
|
|
@ -37,6 +38,7 @@ class VisaCustomerWalletApproveTask(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VisaUtilities.isVisaCard(card.firmwareVersion.doubleValue, card.batchId)) {
|
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(TangemSdkError.Underlying("Can't use Visa card for approve")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -44,7 +46,7 @@ class VisaCustomerWalletApproveTask(
|
||||||
if (visaDataForApprove.customerWalletCardId != null && card.cardId != visaDataForApprove.customerWalletCardId) {
|
if (visaDataForApprove.customerWalletCardId != null && card.cardId != visaDataForApprove.customerWalletCardId) {
|
||||||
callback(
|
callback(
|
||||||
CompletionResult.Failure(
|
CompletionResult.Failure(
|
||||||
TangemSdkError.Underlying("Use tangem wallet specified during visa registration"),
|
TangemSdkError.Underlying("Use tangem wallet specified during visa registration"), // TODO TVF-21
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
@ -74,16 +76,12 @@ class VisaCustomerWalletApproveTask(
|
||||||
}
|
}
|
||||||
|
|
||||||
val derivationPath = VisaUtilities.visaDefaultDerivationPath(derivationStyle) ?: run {
|
val derivationPath = VisaUtilities.visaDefaultDerivationPath(derivationStyle) ?: run {
|
||||||
callback(
|
callback(CompletionResult.Failure(VisaActivationError.FailedToCreateAddress.tangemError))
|
||||||
CompletionResult.Failure(
|
|
||||||
TangemSdkError.Underlying("Failed to generate derivation path with provided derivation style"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val wallet = card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: run {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,7 +121,7 @@ class VisaCustomerWalletApproveTask(
|
||||||
)
|
)
|
||||||
|
|
||||||
validationResult.onLeft {
|
validationResult.onLeft {
|
||||||
callback(CompletionResult.Failure(TangemSdkError.Underlying(it.message)))
|
callback(CompletionResult.Failure(it.tangemError))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,7 +142,7 @@ class VisaCustomerWalletApproveTask(
|
||||||
targetAddress = visaDataForApprove.targetAddress,
|
targetAddress = visaDataForApprove.targetAddress,
|
||||||
card = CardDTO(card),
|
card = CardDTO(card),
|
||||||
).getOrElse {
|
).getOrElse {
|
||||||
callback(CompletionResult.Failure(TangemSdkError.Underlying(it.message)))
|
callback(CompletionResult.Failure(it.tangemError))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,15 @@ import com.tangem.common.core.CardSession
|
||||||
import com.tangem.common.core.TangemSdkError
|
import com.tangem.common.core.TangemSdkError
|
||||||
import com.tangem.common.extensions.hexToBytes
|
import com.tangem.common.extensions.hexToBytes
|
||||||
import com.tangem.common.extensions.toHexString
|
import com.tangem.common.extensions.toHexString
|
||||||
|
import com.tangem.core.error.ext.tangemError
|
||||||
import com.tangem.crypto.hdWallet.DerivationPath
|
import com.tangem.crypto.hdWallet.DerivationPath
|
||||||
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
|
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
|
||||||
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
||||||
import com.tangem.domain.common.visa.VisaUtilities
|
import com.tangem.domain.common.visa.VisaUtilities
|
||||||
import com.tangem.domain.common.visa.VisaWalletPublicKeyUtility
|
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.model.*
|
||||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||||
import com.tangem.domain.visa.repository.VisaAuthRepository
|
import com.tangem.domain.visa.repository.VisaAuthRepository
|
||||||
|
|
@ -71,9 +75,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
||||||
val derivationPath = VisaUtilities.visaDefaultDerivationPath ?: run {
|
val derivationPath = VisaUtilities.visaDefaultDerivationPath ?: run {
|
||||||
Timber.e("Failed to create derivation path while first scan")
|
Timber.e("Failed to create derivation path while first scan")
|
||||||
|
|
||||||
return CompletionResult.Failure(
|
return CompletionResult.Failure(VisaCardScanError.FailedToCreateDerivationPath.tangemError)
|
||||||
TangemSdkError.Underlying(VisaCardScanHandlerError.FailedToCreateDerivationPath.errorDescription),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val derivationTask = DeriveWalletPublicKeyTask(wallet.publicKey, derivationPath)
|
val derivationTask = DeriveWalletPublicKeyTask(wallet.publicKey, derivationPath)
|
||||||
|
|
@ -104,32 +106,24 @@ internal class VisaCardScanHandler @Inject constructor(
|
||||||
|
|
||||||
val derivationPath = VisaUtilities.visaDefaultDerivationPath ?: run {
|
val derivationPath = VisaUtilities.visaDefaultDerivationPath ?: run {
|
||||||
Timber.e("Failed to create derivation path while handling wallet authorization")
|
Timber.e("Failed to create derivation path while handling wallet authorization")
|
||||||
return CompletionResult.Failure(
|
return CompletionResult.Failure(VisaCardScanError.FailedToCreateDerivationPath.tangemError)
|
||||||
TangemSdkError.Underlying(VisaCardScanHandlerError.FailedToCreateDerivationPath.errorDescription),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||||
|
|
||||||
val wallet = card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: run {
|
val wallet = card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: run {
|
||||||
Timber.e("Failed to find extended public key while handling wallet authorization")
|
Timber.e("Failed to find extended public key while handling wallet authorization")
|
||||||
return CompletionResult.Failure(
|
return CompletionResult.Failure(VisaCardScanError.FailedToFindWallet.tangemError)
|
||||||
TangemSdkError.Underlying(VisaCardScanHandlerError.FailedToFindDerivedWalletKey.errorDescription),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val extendedPublicKey = wallet.derivedKeys[derivationPath] ?: run {
|
val extendedPublicKey = wallet.derivedKeys[derivationPath] ?: run {
|
||||||
Timber.e("Failed to find extended public key while handling wallet authorization")
|
Timber.e("Failed to find extended public key while handling wallet authorization")
|
||||||
return CompletionResult.Failure(
|
return CompletionResult.Failure(VisaCardScanError.FailedToFindDerivedWalletKey.tangemError)
|
||||||
TangemSdkError.Underlying(VisaCardScanHandlerError.FailedToFindDerivedWalletKey.errorDescription),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val walletAddress = VisaWalletPublicKeyUtility.generateAddressOnSecp256k1(extendedPublicKey.publicKey)
|
val walletAddress = VisaWalletPublicKeyUtility.generateAddressOnSecp256k1(extendedPublicKey.publicKey)
|
||||||
.getOrElse {
|
.getOrElse {
|
||||||
return CompletionResult.Failure(
|
return CompletionResult.Failure(it.tangemError)
|
||||||
TangemSdkError.Underlying("Cannot generate address on Visa curve"),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Timber.i("Requesting challenge for wallet authorization")
|
Timber.i("Requesting challenge for wallet authorization")
|
||||||
|
|
@ -200,7 +194,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
||||||
)
|
)
|
||||||
}.getOrElse {
|
}.getOrElse {
|
||||||
Timber.e("Failed to get challenge for Card authorization. Plain error: ${it.message}")
|
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}")
|
Timber.i("Received challenge to sign: ${challengeResponse.challenge}")
|
||||||
|
|
@ -230,11 +224,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
||||||
)
|
)
|
||||||
}.getOrElse {
|
}.getOrElse {
|
||||||
Timber.e("Failed to sign challenge with Card public key. Plain error: ${it.message}")
|
Timber.e("Failed to sign challenge with Card public key. Plain error: ${it.message}")
|
||||||
return CompletionResult.Failure(
|
return CompletionResult.Failure(VisaAuthorizationAPIError.tangemError)
|
||||||
TangemSdkError.Underlying(
|
|
||||||
customMessage = it.message ?: "Unknown error",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visaAuthTokenStorage.store(
|
visaAuthTokenStorage.store(
|
||||||
|
|
@ -251,7 +241,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return CompletionResult.Failure(TangemSdkError.Underlying(error.message))
|
return CompletionResult.Failure(error.tangemError)
|
||||||
}
|
}
|
||||||
|
|
||||||
val activationInput = VisaActivationInput(
|
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),
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +1,4 @@
|
||||||
plugins {
|
plugins {
|
||||||
alias(deps.plugins.android.library)
|
alias(deps.plugins.kotlin.jvm)
|
||||||
alias(deps.plugins.kotlin.android)
|
|
||||||
id("configuration")
|
id("configuration")
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace = "com.tangem.core.error"
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(tangemDeps.card.core)
|
|
||||||
implementation(tangemDeps.blockchain)
|
|
||||||
}
|
}
|
||||||
1
core/error/ext/.gitignore
vendored
Normal file
1
core/error/ext/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
||||||
16
core/error/ext/build.gradle.kts
Normal file
16
core/error/ext/build.gradle.kts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
plugins {
|
||||||
|
alias(deps.plugins.android.library)
|
||||||
|
alias(deps.plugins.kotlin.android)
|
||||||
|
id("configuration")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "com.tangem.core.error.ext"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(projects.core.error)
|
||||||
|
|
||||||
|
implementation(tangemDeps.card.core)
|
||||||
|
implementation(tangemDeps.blockchain)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.tangem.core.error.ext
|
||||||
|
|
||||||
|
import com.tangem.common.core.TangemSdkError
|
||||||
|
import com.tangem.blockchain.common.BlockchainSdkError
|
||||||
|
import com.tangem.common.core.TangemError
|
||||||
|
import com.tangem.core.error.UniversalError
|
||||||
|
|
||||||
|
val TangemError.universalError: UniversalError
|
||||||
|
get() = when (this) {
|
||||||
|
is TangemSdkError -> object : UniversalError {
|
||||||
|
override val errorCode: Int = 101000000 + code
|
||||||
|
}
|
||||||
|
else -> object : UniversalError {
|
||||||
|
override val errorCode: Int = code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val BlockchainSdkError.universalError: UniversalError
|
||||||
|
get() = object : UniversalError {
|
||||||
|
override val errorCode: Int = 102000000 + code
|
||||||
|
}
|
||||||
|
|
||||||
|
val UniversalError.tangemError: TangemError
|
||||||
|
get() = object : TangemError(errorCode) {
|
||||||
|
override var customMessage: String = errorCode.toString()
|
||||||
|
override val messageResId: Int? = null
|
||||||
|
}
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package com.tangem.core.error
|
|
||||||
|
|
||||||
import com.tangem.common.core.TangemSdkError
|
|
||||||
import com.tangem.blockchain.common.BlockchainSdkError
|
|
||||||
|
|
||||||
val TangemSdkError.universalError: UniversalError
|
|
||||||
get() = object : UniversalError {
|
|
||||||
override val errorCode: Int = 101000000 + code
|
|
||||||
}
|
|
||||||
|
|
||||||
val BlockchainSdkError.universalError: UniversalError
|
|
||||||
get() = object : UniversalError {
|
|
||||||
override val errorCode: Int = 102000000 + code
|
|
||||||
}
|
|
||||||
|
|
@ -12,6 +12,7 @@ android {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(projects.core.datasource)
|
implementation(projects.core.datasource)
|
||||||
implementation(projects.core.utils)
|
implementation(projects.core.utils)
|
||||||
|
implementation(projects.core.error)
|
||||||
implementation(projects.common)
|
implementation(projects.common)
|
||||||
implementation(projects.libs.auth)
|
implementation(projects.libs.auth)
|
||||||
implementation(projects.libs.blockchainSdk)
|
implementation(projects.libs.blockchainSdk)
|
||||||
|
|
|
||||||
|
|
@ -8,29 +8,33 @@ import com.tangem.blockchain.common.address.AddressType
|
||||||
import com.tangem.common.card.EllipticCurve
|
import com.tangem.common.card.EllipticCurve
|
||||||
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
|
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
import com.tangem.domain.models.scan.CardDTO
|
||||||
|
import com.tangem.domain.visa.error.VisaActivationError
|
||||||
|
|
||||||
object VisaWalletPublicKeyUtility {
|
object VisaWalletPublicKeyUtility {
|
||||||
|
|
||||||
fun validateExtendedPublicKey(targetAddress: String, extendedPublicKey: ExtendedPublicKey): Either<Error, Unit> =
|
fun validateExtendedPublicKey(
|
||||||
either {
|
targetAddress: String,
|
||||||
validatePublicKey(
|
extendedPublicKey: ExtendedPublicKey,
|
||||||
targetAddress = targetAddress,
|
): Either<VisaActivationError, Unit> = either {
|
||||||
publicKey = extendedPublicKey.publicKey,
|
|
||||||
).bind()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun findKeyWithoutDerivation(targetAddress: String, card: CardDTO): Either<Error, ByteArray> = either {
|
|
||||||
val wallet = findWalletOnSecp256k1(card).bind()
|
|
||||||
|
|
||||||
validatePublicKey(
|
validatePublicKey(
|
||||||
targetAddress = targetAddress,
|
targetAddress = targetAddress,
|
||||||
publicKey = wallet.publicKey,
|
publicKey = extendedPublicKey.publicKey,
|
||||||
).bind()
|
).bind()
|
||||||
|
|
||||||
wallet.publicKey
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateAddressOnSecp256k1(walletPublicKey: ByteArray): Either<Error, Address> = either {
|
fun findKeyWithoutDerivation(targetAddress: String, card: CardDTO): Either<VisaActivationError, ByteArray> =
|
||||||
|
either {
|
||||||
|
val wallet = findWalletOnSecp256k1(card).bind()
|
||||||
|
|
||||||
|
validatePublicKey(
|
||||||
|
targetAddress = targetAddress,
|
||||||
|
publicKey = wallet.publicKey,
|
||||||
|
).bind()
|
||||||
|
|
||||||
|
wallet.publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateAddressOnSecp256k1(walletPublicKey: ByteArray): Either<VisaActivationError, Address> = either {
|
||||||
val addresses = catch(
|
val addresses = catch(
|
||||||
block = {
|
block = {
|
||||||
VisaUtilities.visaBlockchain.makeAddresses(
|
VisaUtilities.visaBlockchain.makeAddresses(
|
||||||
|
|
@ -39,27 +43,22 @@ object VisaWalletPublicKeyUtility {
|
||||||
curve = EllipticCurve.Secp256k1,
|
curve = EllipticCurve.Secp256k1,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
catch = { raise(Error.FailedToCreateAddress) },
|
catch = { raise(VisaActivationError.FailedToCreateAddress) },
|
||||||
)
|
)
|
||||||
|
|
||||||
addresses.firstOrNull { it.type == AddressType.Default } ?: raise(Error.FailedToCreateAddress)
|
addresses.firstOrNull { it.type == AddressType.Default } ?: raise(VisaActivationError.FailedToCreateAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findWalletOnSecp256k1(card: CardDTO): Either<Error, CardDTO.Wallet> = either {
|
private fun findWalletOnSecp256k1(card: CardDTO): Either<VisaActivationError, CardDTO.Wallet> = either {
|
||||||
card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: raise(Error.MissingWalletOnTargetCurve)
|
card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: raise(VisaActivationError.MissingWallet)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun validatePublicKey(targetAddress: String, publicKey: ByteArray): Either<Error, Unit> = either {
|
private fun validatePublicKey(targetAddress: String, publicKey: ByteArray): Either<VisaActivationError, Unit> =
|
||||||
val address = generateAddressOnSecp256k1(publicKey).bind()
|
either {
|
||||||
|
val address = generateAddressOnSecp256k1(publicKey).bind()
|
||||||
|
|
||||||
if (address.value != targetAddress) {
|
if (address.value != targetAddress) {
|
||||||
raise(Error.AddressNotMatched)
|
raise(VisaActivationError.AddressNotMatched)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
enum class Error(val message: String) {
|
|
||||||
AddressNotMatched("ValidationError: Address not matched"),
|
|
||||||
FailedToCreateAddress("ValidationError: Failed to create address"),
|
|
||||||
MissingWalletOnTargetCurve("ValidationError: Missing wallet on target curve"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -10,4 +10,5 @@ dependencies {
|
||||||
ksp(deps.moshi.kotlin.codegen)
|
ksp(deps.moshi.kotlin.codegen)
|
||||||
implementation(deps.moshi.adapters)
|
implementation(deps.moshi.adapters)
|
||||||
implementation(deps.kotlin.serialization)
|
implementation(deps.kotlin.serialization)
|
||||||
|
implementation(projects.core.error)
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
@file:Suppress("MagicNumber")
|
||||||
|
|
||||||
|
package com.tangem.domain.visa.error
|
||||||
|
|
||||||
|
import com.tangem.core.error.UniversalError
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each error code must follow this format: xxxyyyzzz where
|
||||||
|
* xxx - Feature code
|
||||||
|
* yyy - Subsystem code
|
||||||
|
* zzz - Specific error code
|
||||||
|
* If you need to add new subsystem add it to list below incrementing last code.
|
||||||
|
* `Subsystems`:
|
||||||
|
* `001` - Common API
|
||||||
|
* `002` - First card scan error
|
||||||
|
* `003` - Activation
|
||||||
|
* `004` - Authorization API
|
||||||
|
*/
|
||||||
|
object VisaError : UniversalError {
|
||||||
|
override val errorCode: Int = 104000000
|
||||||
|
}
|
||||||
|
|
||||||
|
object VisaAPIError : UniversalError {
|
||||||
|
override val errorCode: Int = 104001000
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class VisaCardScanError(
|
||||||
|
override val errorCode: Int,
|
||||||
|
) : UniversalError {
|
||||||
|
FailedToCreateDerivationPath(104002001),
|
||||||
|
FailedToFindWallet(104002002),
|
||||||
|
FailedToFindDerivedWalletKey(104002003),
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class VisaActivationError(
|
||||||
|
override val errorCode: Int,
|
||||||
|
) : UniversalError {
|
||||||
|
BlockedForActivation(104003001),
|
||||||
|
InvalidActivationState(104003002),
|
||||||
|
WrongCard(104003003),
|
||||||
|
WrongRemoteState(104003004),
|
||||||
|
MissingWallet(104003005),
|
||||||
|
MissingRootOTP(104003006),
|
||||||
|
FailedToCreateAddress(104003007),
|
||||||
|
AddressNotMatched(104003008),
|
||||||
|
InconsistentRemoteState(104003009),
|
||||||
|
}
|
||||||
|
|
||||||
|
object VisaAuthorizationAPIError : UniversalError {
|
||||||
|
override val errorCode: Int = 104004000
|
||||||
|
}
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
package com.tangem.domain.visa.model
|
|
||||||
|
|
||||||
enum class VisaActivationError(val message: String) {
|
|
||||||
BlockedForActivation("Card is blocked for activation"),
|
|
||||||
InvalidActivationState("Invalid activation state"),
|
|
||||||
WrongCard("Wrong card tapped"),
|
|
||||||
WrongRemoteState("Wrong remote state"),
|
|
||||||
MissingWallet("Missing wallet"),
|
|
||||||
MissingRootOTP("Missing root OTP"),
|
|
||||||
}
|
|
||||||
|
|
@ -27,6 +27,7 @@ dependencies {
|
||||||
implementation(projects.core.decompose)
|
implementation(projects.core.decompose)
|
||||||
implementation(projects.core.navigation)
|
implementation(projects.core.navigation)
|
||||||
implementation(projects.core.datasource)
|
implementation(projects.core.datasource)
|
||||||
|
implementation(projects.core.error.ext)
|
||||||
|
|
||||||
/** Common */
|
/** Common */
|
||||||
implementation(projects.common.ui)
|
implementation(projects.common.ui)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,11 @@ import com.tangem.common.extensions.toHexString
|
||||||
import com.tangem.core.decompose.di.ModelScoped
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
|
import com.tangem.core.decompose.ui.UiMessageSender
|
||||||
|
import com.tangem.core.error.ext.universalError
|
||||||
|
import com.tangem.core.ui.utils.showErrorDialog
|
||||||
|
import com.tangem.domain.visa.error.VisaAPIError
|
||||||
|
import com.tangem.domain.visa.error.VisaAuthorizationAPIError
|
||||||
import com.tangem.domain.visa.model.VisaCardActivationStatus
|
import com.tangem.domain.visa.model.VisaCardActivationStatus
|
||||||
import com.tangem.domain.visa.model.VisaCardId
|
import com.tangem.domain.visa.model.VisaCardId
|
||||||
import com.tangem.domain.visa.model.VisaCustomerWalletDataToSignRequest
|
import com.tangem.domain.visa.model.VisaCustomerWalletDataToSignRequest
|
||||||
|
|
@ -34,6 +39,7 @@ internal class OnboardingVisaAccessCodeModel @Inject constructor(
|
||||||
@Suppress("UnusedPrivateMember")
|
@Suppress("UnusedPrivateMember")
|
||||||
private val tangemSdkManager: TangemSdkManager,
|
private val tangemSdkManager: TangemSdkManager,
|
||||||
private val visaAuthRepository: VisaAuthRepository,
|
private val visaAuthRepository: VisaAuthRepository,
|
||||||
|
private val uiMessageSender: UiMessageSender,
|
||||||
) : Model() {
|
) : Model() {
|
||||||
|
|
||||||
private val params: OnboardingVisaAccessCodeComponent.Config = paramsContainer.require()
|
private val params: OnboardingVisaAccessCodeComponent.Config = paramsContainer.require()
|
||||||
|
|
@ -138,7 +144,7 @@ internal class OnboardingVisaAccessCodeModel @Inject constructor(
|
||||||
)
|
)
|
||||||
}.getOrElse {
|
}.getOrElse {
|
||||||
loading(false)
|
loading(false)
|
||||||
// TODO show alert
|
uiMessageSender.showErrorDialog(VisaAuthorizationAPIError)
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,17 +154,22 @@ internal class OnboardingVisaAccessCodeModel @Inject constructor(
|
||||||
authorizationChallenge = challengeToSign,
|
authorizationChallenge = challengeToSign,
|
||||||
),
|
),
|
||||||
activationInput = activationStatus.activationInput,
|
activationInput = activationStatus.activationInput,
|
||||||
) as? CompletionResult.Success ?: run {
|
)
|
||||||
loading(false)
|
|
||||||
// TODO show alert
|
val resultData = when (result) {
|
||||||
return@launch
|
is CompletionResult.Failure -> {
|
||||||
|
loading(false)
|
||||||
|
uiMessageSender.showErrorDialog(result.error.universalError)
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
is CompletionResult.Success -> result.data
|
||||||
}
|
}
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
visaActivationRepository.activateCard(result.data.signedActivationData)
|
visaActivationRepository.activateCard(resultData.signedActivationData)
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
loading(false)
|
loading(false)
|
||||||
// TODO show alert
|
uiMessageSender.showErrorDialog(VisaAPIError)
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,10 @@ import com.tangem.common.extensions.toHexString
|
||||||
import com.tangem.core.decompose.di.ModelScoped
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
|
import com.tangem.core.decompose.ui.UiMessageSender
|
||||||
|
import com.tangem.core.error.ext.universalError
|
||||||
|
import com.tangem.core.ui.utils.showErrorDialog
|
||||||
|
import com.tangem.domain.visa.error.VisaAPIError
|
||||||
import com.tangem.domain.visa.model.VisaCardId
|
import com.tangem.domain.visa.model.VisaCardId
|
||||||
import com.tangem.domain.visa.model.VisaDataForApprove
|
import com.tangem.domain.visa.model.VisaDataForApprove
|
||||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||||
|
|
@ -27,6 +31,7 @@ internal class OnboardingVisaApproveModel @Inject constructor(
|
||||||
visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||||
override val dispatchers: CoroutineDispatcherProvider,
|
override val dispatchers: CoroutineDispatcherProvider,
|
||||||
private val tangemSdkManager: TangemSdkManager,
|
private val tangemSdkManager: TangemSdkManager,
|
||||||
|
private val uiMessageSender: UiMessageSender,
|
||||||
) : Model() {
|
) : Model() {
|
||||||
|
|
||||||
private val params = paramsContainer.require<OnboardingVisaApproveComponent.Config>()
|
private val params = paramsContainer.require<OnboardingVisaApproveComponent.Config>()
|
||||||
|
|
@ -56,7 +61,7 @@ internal class OnboardingVisaApproveModel @Inject constructor(
|
||||||
visaActivationRepository.getCustomerWalletAcceptanceData(params.preparationDataForApprove.request)
|
visaActivationRepository.getCustomerWalletAcceptanceData(params.preparationDataForApprove.request)
|
||||||
}.getOrElse {
|
}.getOrElse {
|
||||||
loading(false)
|
loading(false)
|
||||||
// TODO show dialog
|
uiMessageSender.showErrorDialog(VisaAPIError)
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,17 +71,22 @@ internal class OnboardingVisaApproveModel @Inject constructor(
|
||||||
targetAddress = params.preparationDataForApprove.customerWalletAddress,
|
targetAddress = params.preparationDataForApprove.customerWalletAddress,
|
||||||
dataToSign = dataToSign,
|
dataToSign = dataToSign,
|
||||||
),
|
),
|
||||||
) as? CompletionResult.Success ?: run {
|
)
|
||||||
loading(false)
|
|
||||||
// TODO show dialog
|
val resultData = when (result) {
|
||||||
return@launch
|
is CompletionResult.Failure -> {
|
||||||
|
loading(false)
|
||||||
|
uiMessageSender.showErrorDialog(result.error.universalError)
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
is CompletionResult.Success -> result.data
|
||||||
}
|
}
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
visaActivationRepository.approveByCustomerWallet(result.data)
|
visaActivationRepository.approveByCustomerWallet(resultData)
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
loading(false)
|
loading(false)
|
||||||
// TODO show dialog
|
uiMessageSender.showErrorDialog(VisaAPIError)
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,13 @@ import com.tangem.common.extensions.toHexString
|
||||||
import com.tangem.core.decompose.di.ModelScoped
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
|
import com.tangem.core.decompose.ui.UiMessageSender
|
||||||
|
import com.tangem.core.ui.utils.showErrorDialog
|
||||||
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
||||||
import com.tangem.datasource.local.visa.VisaOTPStorage
|
import com.tangem.datasource.local.visa.VisaOTPStorage
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
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.model.*
|
||||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||||
import com.tangem.domain.visa.repository.VisaAuthRepository
|
import com.tangem.domain.visa.repository.VisaAuthRepository
|
||||||
|
|
@ -36,6 +40,7 @@ internal class OnboardingVisaInProgressModel @Inject constructor(
|
||||||
private val otpStorage: VisaOTPStorage,
|
private val otpStorage: VisaOTPStorage,
|
||||||
private val userWalletBuilderFactory: UserWalletBuilder.Factory,
|
private val userWalletBuilderFactory: UserWalletBuilder.Factory,
|
||||||
private val userWalletsListManager: UserWalletsListManager,
|
private val userWalletsListManager: UserWalletsListManager,
|
||||||
|
private val uiMessageSender: UiMessageSender,
|
||||||
) : Model() {
|
) : Model() {
|
||||||
|
|
||||||
private val params = paramsContainer.require<Config>()
|
private val params = paramsContainer.require<Config>()
|
||||||
|
|
@ -58,7 +63,7 @@ internal class OnboardingVisaInProgressModel @Inject constructor(
|
||||||
is VisaActivationRemoteState.CardWalletSignatureRequired,
|
is VisaActivationRemoteState.CardWalletSignatureRequired,
|
||||||
VisaActivationRemoteState.BlockedForActivation,
|
VisaActivationRemoteState.BlockedForActivation,
|
||||||
-> {
|
-> {
|
||||||
// TODO show alert inconsistent state
|
uiMessageSender.showErrorDialog(VisaActivationError.InconsistentRemoteState)
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
is VisaActivationRemoteState.CustomerWalletSignatureRequired,
|
is VisaActivationRemoteState.CustomerWalletSignatureRequired,
|
||||||
|
|
@ -92,7 +97,7 @@ internal class OnboardingVisaInProgressModel @Inject constructor(
|
||||||
val newTokens = runCatching {
|
val newTokens = runCatching {
|
||||||
visaAuthRepository.refreshAccessTokens(authTokens.refreshToken)
|
visaAuthRepository.refreshAccessTokens(authTokens.refreshToken)
|
||||||
}.getOrElse {
|
}.getOrElse {
|
||||||
// TODO show alert
|
uiMessageSender.showErrorDialog(VisaAuthorizationAPIError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,10 @@ import com.tangem.common.extensions.toHexString
|
||||||
import com.tangem.core.decompose.di.ModelScoped
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
|
import com.tangem.core.decompose.ui.UiMessageSender
|
||||||
|
import com.tangem.core.error.ext.universalError
|
||||||
|
import com.tangem.core.ui.utils.showErrorDialog
|
||||||
|
import com.tangem.domain.visa.error.VisaAPIError
|
||||||
import com.tangem.domain.visa.model.VisaCardId
|
import com.tangem.domain.visa.model.VisaCardId
|
||||||
import com.tangem.domain.visa.model.VisaCustomerWalletDataToSignRequest
|
import com.tangem.domain.visa.model.VisaCustomerWalletDataToSignRequest
|
||||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||||
|
|
@ -28,6 +32,7 @@ internal class OnboardingVisaWelcomeModel @Inject constructor(
|
||||||
override val dispatchers: CoroutineDispatcherProvider,
|
override val dispatchers: CoroutineDispatcherProvider,
|
||||||
private val tangemSdkManager: TangemSdkManager,
|
private val tangemSdkManager: TangemSdkManager,
|
||||||
private val visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
private val visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||||
|
private val uiMessageSender: UiMessageSender,
|
||||||
) : Model() {
|
) : Model() {
|
||||||
|
|
||||||
private val params = paramsContainer.require<Config>()
|
private val params = paramsContainer.require<Config>()
|
||||||
|
|
@ -68,24 +73,29 @@ internal class OnboardingVisaWelcomeModel @Inject constructor(
|
||||||
visaActivationRepository.getCardWalletAcceptanceData(params.dataToSignRequest)
|
visaActivationRepository.getCardWalletAcceptanceData(params.dataToSignRequest)
|
||||||
}.getOrElse {
|
}.getOrElse {
|
||||||
loading(false)
|
loading(false)
|
||||||
// TODO show alert
|
uiMessageSender.showErrorDialog(VisaAPIError)
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = tangemSdkManager.activateVisaCard(
|
val result = tangemSdkManager.activateVisaCard(
|
||||||
mode = VisaCardActivationTaskMode.SignOnly(dataToSignByCardWallet = dataToSignByCardWallet),
|
mode = VisaCardActivationTaskMode.SignOnly(dataToSignByCardWallet = dataToSignByCardWallet),
|
||||||
activationInput = params.activationInput,
|
activationInput = params.activationInput,
|
||||||
) as? CompletionResult.Success ?: run {
|
)
|
||||||
loading(false)
|
|
||||||
// TODO show alert
|
val resultData = when (result) {
|
||||||
return@launch
|
is CompletionResult.Failure -> {
|
||||||
|
loading(false)
|
||||||
|
uiMessageSender.showErrorDialog(result.error.universalError)
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
is CompletionResult.Success -> result.data
|
||||||
}
|
}
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
visaActivationRepository.activateCard(result.data.signedActivationData)
|
visaActivationRepository.activateCard(resultData.signedActivationData)
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
loading(false)
|
loading(false)
|
||||||
// TODO show alert
|
uiMessageSender.showErrorDialog(VisaAPIError)
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,7 @@ include(":core:deep-links:global")
|
||||||
include(":core:decompose")
|
include(":core:decompose")
|
||||||
include(":core:pagination")
|
include(":core:pagination")
|
||||||
include(":core:error")
|
include(":core:error")
|
||||||
|
include(":core:error:ext")
|
||||||
// endregion Core modules
|
// endregion Core modules
|
||||||
|
|
||||||
// region Common modules
|
// region Common modules
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue