Updated on 2026-08-14

This commit is contained in:
Tangem 2025-06-17 11:20:30 +03:00
parent 422e406d15
commit 7c91472d99
7 changed files with 26 additions and 12 deletions

View file

@ -83,11 +83,14 @@ internal class VisaCardScanHandler @Inject constructor(
Timber.i("Requesting challenge for wallet authorization")
val challengeResponse = visaAuthRepository.getCardWalletAuthChallenge(cardWalletAddress = walletAddress.value)
.getOrElse {
Timber.i("Failed to get Access token for Wallet public key authorization")
return CompletionResult.Failure(it.tangemError)
}
val challengeResponse = visaAuthRepository.getCardWalletAuthChallenge(
cardId = card.cardId,
// This is the wallet public key, not the address and it's alright, as the API expects it in this format
cardWalletAddress = wallet.publicKey.toHexString(),
).getOrElse {
Timber.i("Failed to get Access token for Wallet public key authorization")
return CompletionResult.Failure(it.tangemError)
}
val signChallengeResult = signChallengeWithWallet(
publicKey = wallet.publicKey,
@ -96,15 +99,16 @@ internal class VisaCardScanHandler @Inject constructor(
return when (signChallengeResult) {
is CompletionResult.Success -> {
val signature = signChallengeResult.data.cardSignature ?: run {
Timber.i("Failed to sign challenge with Wallet public key")
return CompletionResult.Failure(VisaCardScanError.FailedToSignChallenge.tangemError)
}
val signature = signChallengeResult.data.walletSignature
val salt = signChallengeResult.data.salt
Timber.i("Challenge signed with Wallet public key")
handleWalletAuthorizationTokens(
cardWalletAddress = walletAddress.value,
signedChallenge = challengeResponse.toSignedChallenge(signature.toHexString()),
signedChallenge = challengeResponse.toSignedChallenge(
signedChallenge = signature.toHexString(),
salt = salt.toHexString(),
),
)
}
is CompletionResult.Failure -> {

View file

@ -7,4 +7,5 @@ import com.squareup.moshi.JsonClass
data class GenerateNoneByCardWalletRequest(
@Json(name = "auth_type") val authType: String = "card_wallet",
@Json(name = "card_wallet_address") val cardWalletAddress: String,
@Json(name = "card_id") val cardId: String,
)

View file

@ -8,4 +8,5 @@ data class GetAccessTokenByCardWalletRequest(
@Json(name = "auth_type") val authType: String = "card_wallet",
@Json(name = "session_id") val sessionId: String,
@Json(name = "signature") val signature: String,
@Json(name = "salt") val salt: String,
)

View file

@ -47,12 +47,14 @@ internal class DefaultVisaAuthRepository @Inject constructor(
}
override suspend fun getCardWalletAuthChallenge(
cardId: String,
cardWalletAddress: String,
): Either<VisaApiError, VisaAuthChallenge.Wallet> = withContext(dispatchers.io) {
request {
visaAuthApi.generateNonceByCardWallet(
GenerateNoneByCardWalletRequest(
cardWalletAddress = cardWalletAddress,
cardId = cardId,
),
).getOrThrow()
}.map { response ->
@ -82,6 +84,7 @@ internal class DefaultVisaAuthRepository @Inject constructor(
GetAccessTokenByCardWalletRequest(
sessionId = signedChallenge.challenge.session.sessionId,
signature = signedChallenge.signature,
salt = signedChallenge.salt,
),
).getOrThrow()
}

View file

@ -23,9 +23,10 @@ fun VisaAuthChallenge.Card.toSignedChallenge(signedChallenge: String, salt: Stri
)
}
fun VisaAuthChallenge.Wallet.toSignedChallenge(signedChallenge: String): VisaAuthSignedChallenge {
fun VisaAuthChallenge.Wallet.toSignedChallenge(signedChallenge: String, salt: String): VisaAuthSignedChallenge {
return VisaAuthSignedChallenge.ByWallet(
challenge = this,
signature = signedChallenge,
salt = salt,
)
}

View file

@ -11,5 +11,6 @@ sealed class VisaAuthSignedChallenge {
data class ByWallet(
val challenge: VisaAuthChallenge.Wallet,
val signature: String,
val salt: String,
) : VisaAuthSignedChallenge()
}

View file

@ -13,7 +13,10 @@ interface VisaAuthRepository {
cardPublicKey: String,
): Either<VisaApiError, VisaAuthChallenge.Card>
suspend fun getCardWalletAuthChallenge(cardWalletAddress: String): Either<VisaApiError, VisaAuthChallenge.Wallet>
suspend fun getCardWalletAuthChallenge(
cardId: String,
cardWalletAddress: String,
): Either<VisaApiError, VisaAuthChallenge.Wallet>
suspend fun getAccessTokens(signedChallenge: VisaAuthSignedChallenge): Either<VisaApiError, VisaAuthTokens>