Updated on 2026-08-14
This commit is contained in:
parent
2709b9d5b4
commit
9a95b49b4a
13 changed files with 103 additions and 87 deletions
|
|
@ -33,22 +33,20 @@ internal class DefaultVisaAuthTokenStorage @Inject constructor(
|
|||
|
||||
private val tokensAdapter = moshi.adapter(VisaAuthTokens::class.java)
|
||||
|
||||
override suspend fun store(tokens: VisaAuthTokens) = withContext(dispatcherProvider.io) {
|
||||
override suspend fun store(cardId: String, tokens: VisaAuthTokens) = withContext(dispatcherProvider.io) {
|
||||
val json = tokensAdapter.toJson(tokens)
|
||||
|
||||
secureStorage.store(
|
||||
json.encodeToByteArray(throwOnInvalidSequence = true),
|
||||
VISA_AUTH_TOKENS_KEY,
|
||||
createKey(cardId),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun get(): VisaAuthTokens? = withContext(dispatcherProvider.io) {
|
||||
secureStorage.get(VISA_AUTH_TOKENS_KEY)
|
||||
override suspend fun get(cardId: String): VisaAuthTokens? = withContext(dispatcherProvider.io) {
|
||||
secureStorage.get(createKey(cardId))
|
||||
?.decodeToString(throwOnInvalidSequence = true)
|
||||
?.let(tokensAdapter::fromJson)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val VISA_AUTH_TOKENS_KEY = "visa_auth_tokens"
|
||||
}
|
||||
private fun createKey(cardId: String): String = "visa_auth_tokens_$cardId"
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.domain.tasks.visa
|
|||
|
||||
import com.reown.util.hexToBytes
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.common.core.CardSession
|
||||
import com.tangem.common.core.CardSessionRunnable
|
||||
import com.tangem.common.core.CompletionCallback
|
||||
|
|
@ -36,9 +37,15 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
private val otpStorage: VisaOTPStorage,
|
||||
private val visaAuthTokenStorage: VisaAuthTokenStorage,
|
||||
private val visaAuthRepository: VisaAuthRepository,
|
||||
private val visaActivationRepository: VisaActivationRepository,
|
||||
private val visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||
) : CardSessionRunnable<VisaCardActivationResponse> {
|
||||
|
||||
private class SessionContext(
|
||||
val visaActivationRepository: VisaActivationRepository,
|
||||
val card: Card,
|
||||
val session: CardSession,
|
||||
)
|
||||
|
||||
override fun run(session: CardSession, callback: CompletionCallback<VisaCardActivationResponse>) {
|
||||
coroutineScope.launch {
|
||||
callback(runSuspend(session))
|
||||
|
|
@ -52,20 +59,27 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
return CompletionResult.Failure(TangemSdkError.Underlying(VisaActivationError.WrongCard.message))
|
||||
}
|
||||
|
||||
val visaActivationRepository = visaActivationRepositoryFactory.create(card.cardId)
|
||||
|
||||
val context = SessionContext(
|
||||
visaActivationRepository = visaActivationRepository,
|
||||
card = card,
|
||||
session = session,
|
||||
)
|
||||
|
||||
return if (challengeToSign != null) {
|
||||
signAuthorizationChallenge(session, challengeToSign)
|
||||
context.signAuthorizationChallenge(challengeToSign)
|
||||
} else {
|
||||
val activationOrder = runCatching { visaActivationRepository.getActivationOrderToSign() }
|
||||
.getOrElse {
|
||||
return CompletionResult.Failure(TangemSdkError.Underlying(it.message ?: ""))
|
||||
}
|
||||
|
||||
signOrder(session, activationOrder)
|
||||
context.signOrder(activationOrder)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun signAuthorizationChallenge(
|
||||
session: CardSession,
|
||||
private suspend fun SessionContext.signAuthorizationChallenge(
|
||||
challengeToSign: VisaAuthChallenge.Card,
|
||||
): CompletionResult<VisaCardActivationResponse> {
|
||||
val attestationCommand = AttestCardKeyCommand(challenge = challengeToSign.challenge.hexToBytes())
|
||||
|
|
@ -78,7 +92,6 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
return when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
processSignedAuthorizationChallenge(
|
||||
session = session,
|
||||
signedChallenge = challengeToSign.toSignedChallenge(
|
||||
signedChallenge = result.data.cardSignature.toHexString(),
|
||||
salt = result.data.salt.toHexString(),
|
||||
|
|
@ -91,8 +104,7 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun processSignedAuthorizationChallenge(
|
||||
session: CardSession,
|
||||
private suspend fun SessionContext.processSignedAuthorizationChallenge(
|
||||
signedChallenge: VisaAuthSignedChallenge,
|
||||
): CompletionResult<VisaCardActivationResponse> {
|
||||
return coroutineScope {
|
||||
|
|
@ -107,12 +119,14 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
|
||||
otpTaskDeferred.await()
|
||||
|
||||
signOrder(session, order)
|
||||
signOrder(order)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(TangemSdkError::class)
|
||||
private suspend fun getActivationOrderToSign(signedChallenge: VisaAuthSignedChallenge): ActivationOrder {
|
||||
private suspend fun SessionContext.getActivationOrderToSign(
|
||||
signedChallenge: VisaAuthSignedChallenge,
|
||||
): ActivationOrder {
|
||||
val tokens = runCatching {
|
||||
visaAuthRepository.getAccessTokens(signedChallenge)
|
||||
}.getOrElse {
|
||||
|
|
@ -121,7 +135,7 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
visaAuthTokenStorage.store(tokens)
|
||||
visaAuthTokenStorage.store(card.cardId, tokens)
|
||||
|
||||
return visaActivationRepository.getActivationOrderToSign()
|
||||
}
|
||||
|
|
@ -180,11 +194,7 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun signOrder(
|
||||
session: CardSession,
|
||||
order: ActivationOrder,
|
||||
): CompletionResult<VisaCardActivationResponse> {
|
||||
val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||
private suspend fun SessionContext.signOrder(order: ActivationOrder): CompletionResult<VisaCardActivationResponse> {
|
||||
val wallet =
|
||||
card.wallets.firstOrNull() ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||
val task = SignHashCommand(order.hash.hexToBytes(), wallet.publicKey)
|
||||
|
|
@ -197,7 +207,6 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
return when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
handleSignedOrder(
|
||||
session = session,
|
||||
activationOrder = order,
|
||||
response = result.data,
|
||||
)
|
||||
|
|
@ -208,13 +217,10 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun handleSignedOrder(
|
||||
session: CardSession,
|
||||
private suspend fun SessionContext.handleSignedOrder(
|
||||
activationOrder: ActivationOrder,
|
||||
response: SignHashResponse,
|
||||
): CompletionResult<VisaCardActivationResponse> {
|
||||
val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||
|
||||
val signedOrder = SignedActivationOrder(
|
||||
activationOrder = activationOrder,
|
||||
signature = response.signature.toHexString(),
|
||||
|
|
@ -232,9 +238,7 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
return setupAccessCode(session).map { activationResponse }
|
||||
}
|
||||
|
||||
private suspend fun setupAccessCode(session: CardSession): CompletionResult<Unit> {
|
||||
val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||
|
||||
private suspend fun SessionContext.setupAccessCode(session: CardSession): CompletionResult<Unit> {
|
||||
if (card.isAccessCodeSet) {
|
||||
return CompletionResult.Success(Unit)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.domain.visa
|
||||
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.common.card.CardWallet
|
||||
import com.tangem.common.core.CardSession
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
|
|
@ -24,10 +25,16 @@ import kotlin.coroutines.resume
|
|||
|
||||
internal class VisaCardScanHandler @Inject constructor(
|
||||
private val visaAuthRepository: VisaAuthRepository,
|
||||
private val visaActivationRepository: VisaActivationRepository,
|
||||
private val visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||
private val visaAuthTokenStorage: VisaAuthTokenStorage,
|
||||
) {
|
||||
|
||||
private class SessionContext(
|
||||
val visaActivationRepository: VisaActivationRepository,
|
||||
val card: Card,
|
||||
val session: CardSession,
|
||||
)
|
||||
|
||||
suspend fun handleVisaCardScan(session: CardSession): CompletionResult<VisaCardActivationStatus> {
|
||||
Timber.i("Attempting to handle Visa card scan")
|
||||
|
||||
|
|
@ -36,6 +43,14 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||
}
|
||||
|
||||
val visaActivationRepository = visaActivationRepositoryFactory.create(card.cardId)
|
||||
|
||||
val context = SessionContext(
|
||||
visaActivationRepository = visaActivationRepository,
|
||||
card = card,
|
||||
session = session,
|
||||
)
|
||||
|
||||
val wallet = card.wallets.firstOrNull { it.curve == VisaUtilities.mandatoryCurve } ?: run {
|
||||
val activationInput =
|
||||
VisaActivationInput(card.cardId, card.cardPublicKey, card.isAccessCodeSet)
|
||||
|
|
@ -43,13 +58,10 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
return CompletionResult.Success(activationStatus)
|
||||
}
|
||||
|
||||
return deriveKey(wallet, session)
|
||||
return context.deriveKey(wallet)
|
||||
}
|
||||
|
||||
private suspend fun deriveKey(
|
||||
wallet: CardWallet,
|
||||
session: CardSession,
|
||||
): CompletionResult<VisaCardActivationStatus> {
|
||||
private suspend fun SessionContext.deriveKey(wallet: CardWallet): CompletionResult<VisaCardActivationStatus> {
|
||||
val derivationPath = VisaUtilities.visaDefaultDerivationPath ?: run {
|
||||
Timber.e("Failed to create derivation path while first scan")
|
||||
|
||||
|
|
@ -64,17 +76,16 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
continuation.resume(result)
|
||||
}
|
||||
}
|
||||
return handleDerivationResponse(derivationTaskResult, session)
|
||||
return handleDerivationResponse(derivationTaskResult)
|
||||
}
|
||||
|
||||
private suspend fun handleDerivationResponse(
|
||||
private suspend fun SessionContext.handleDerivationResponse(
|
||||
result: CompletionResult<ExtendedPublicKey>,
|
||||
session: CardSession,
|
||||
): CompletionResult<VisaCardActivationStatus> {
|
||||
return when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
Timber.i("Start task for loading challenge for Visa wallet")
|
||||
handleWalletAuthorization(session)
|
||||
handleWalletAuthorization()
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
CompletionResult.Failure(result.error)
|
||||
|
|
@ -82,9 +93,8 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun handleWalletAuthorization(session: CardSession): CompletionResult<VisaCardActivationStatus> {
|
||||
private suspend fun SessionContext.handleWalletAuthorization(): CompletionResult<VisaCardActivationStatus> {
|
||||
Timber.i("Started handling authorization using Visa wallet")
|
||||
val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||
|
||||
val derivationPath = VisaUtilities.visaDefaultDerivationPath ?: run {
|
||||
Timber.e("Failed to create derivation path while handling wallet authorization")
|
||||
|
|
@ -122,14 +132,12 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
publicKey = wallet.publicKey,
|
||||
derivationPath = derivationPath,
|
||||
nonce = challengeResponse.challenge,
|
||||
session = session,
|
||||
)
|
||||
|
||||
return when (signChallengeResult) {
|
||||
is CompletionResult.Success -> {
|
||||
Timber.i("Challenge signed with Wallet public key")
|
||||
handleWalletAuthorizationTokens(
|
||||
session = session,
|
||||
signedChallenge = challengeResponse
|
||||
.toSignedChallenge(signChallengeResult.data.signature.toHexString()),
|
||||
)
|
||||
|
|
@ -141,27 +149,31 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun handleWalletAuthorizationTokens(
|
||||
session: CardSession,
|
||||
private suspend fun SessionContext.handleWalletAuthorizationTokens(
|
||||
signedChallenge: VisaAuthSignedChallenge,
|
||||
): CompletionResult<VisaCardActivationStatus> {
|
||||
val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||
|
||||
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",
|
||||
)
|
||||
return handleCardAuthorization(session)
|
||||
return handleCardAuthorization()
|
||||
}
|
||||
|
||||
visaAuthTokenStorage.store(authorizationTokensResponse)
|
||||
visaAuthTokenStorage.store(
|
||||
cardId = card.cardId,
|
||||
tokens = authorizationTokensResponse,
|
||||
)
|
||||
|
||||
Timber.i("Authorized using Wallet public key successfully")
|
||||
|
||||
return CompletionResult.Success(VisaCardActivationStatus.Activated(authorizationTokensResponse))
|
||||
}
|
||||
|
||||
private suspend fun handleCardAuthorization(session: CardSession): CompletionResult<VisaCardActivationStatus> {
|
||||
private suspend fun SessionContext.handleCardAuthorization(): CompletionResult<VisaCardActivationStatus> {
|
||||
val card = session.environment.card ?: return CompletionResult.Failure(TangemSdkError.MissingPreflightRead())
|
||||
|
||||
Timber.i("Requesting authorization challenge to sign")
|
||||
|
|
@ -178,7 +190,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
|
||||
Timber.i("Received challenge to sign: ${challengeResponse.challenge}")
|
||||
|
||||
val signChallengeResult = signChallengeWithCard(session = session, challenge = challengeResponse.challenge)
|
||||
val signChallengeResult = signChallengeWithCard(challenge = challengeResponse.challenge)
|
||||
|
||||
val attestCardKeyResponse = when (signChallengeResult) {
|
||||
is CompletionResult.Success -> {
|
||||
|
|
@ -210,7 +222,10 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
visaAuthTokenStorage.store(authorizationTokensResponse)
|
||||
visaAuthTokenStorage.store(
|
||||
cardId = card.cardId,
|
||||
tokens = authorizationTokensResponse,
|
||||
)
|
||||
|
||||
val activationRemoteState = visaActivationRepository.getActivationRemoteState()
|
||||
|
||||
|
|
@ -239,11 +254,10 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun signChallengeWithWallet(
|
||||
private suspend fun SessionContext.signChallengeWithWallet(
|
||||
publicKey: ByteArray,
|
||||
derivationPath: DerivationPath,
|
||||
nonce: String,
|
||||
session: CardSession,
|
||||
): CompletionResult<SignHashResponse> {
|
||||
val signHashCommand = SignHashCommand(publicKey, nonce.toByteArray(), derivationPath)
|
||||
val result = suspendCancellableCoroutine {
|
||||
|
|
@ -262,8 +276,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun signChallengeWithCard(
|
||||
session: CardSession,
|
||||
private suspend fun SessionContext.signChallengeWithCard(
|
||||
challenge: String,
|
||||
): CompletionResult<AttestCardKeyResponse> {
|
||||
val signHashCommand = AttestCardKeyCommand(challenge = challenge.toByteArray())
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ internal class DefaultVisaAuthProvider @Inject constructor(
|
|||
private val authStorage: VisaAuthTokenStorage,
|
||||
) : TangemVisaAuthProvider {
|
||||
|
||||
override suspend fun getAuthHeader(): String {
|
||||
return authStorage.get()?.accessToken?.let { "Bearer $it" } ?: "Error in the app!"
|
||||
override suspend fun getAuthHeader(cardId: String): String {
|
||||
return authStorage.get(cardId)?.accessToken?.let { "Bearer $it" } ?: "Error in the app!"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,8 @@
|
|||
package com.tangem.datasource.api.common.config
|
||||
|
||||
import com.tangem.datasource.api.common.visa.TangemVisaAuthProvider
|
||||
import com.tangem.utils.ProviderSuspend
|
||||
|
||||
internal class TangemVisa(
|
||||
private val authProvider: TangemVisaAuthProvider,
|
||||
) : ApiConfig() {
|
||||
internal class TangemVisa : ApiConfig() {
|
||||
|
||||
override val defaultEnvironment: ApiEnvironment = ApiEnvironment.PROD
|
||||
|
||||
|
|
@ -19,7 +16,5 @@ internal class TangemVisa(
|
|||
headers = createHeaders(),
|
||||
)
|
||||
|
||||
private fun createHeaders() = mapOf(
|
||||
"Authorization" to ProviderSuspend { authProvider.getAuthHeader() },
|
||||
)
|
||||
private fun createHeaders() = mapOf<String, ProviderSuspend<String>>()
|
||||
}
|
||||
|
|
@ -2,5 +2,5 @@ package com.tangem.datasource.api.common.visa
|
|||
|
||||
interface TangemVisaAuthProvider {
|
||||
|
||||
suspend fun getAuthHeader(): String
|
||||
suspend fun getAuthHeader(cardId: String): String
|
||||
}
|
||||
|
|
@ -2,9 +2,12 @@ package com.tangem.datasource.api.visa
|
|||
|
||||
import com.tangem.datasource.api.visa.models.response.CardActivationRemoteStateResponse
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
|
||||
interface TangemVisaApi {
|
||||
|
||||
@GET("activation-status")
|
||||
suspend fun getRemoteActivationStatus(): CardActivationRemoteStateResponse
|
||||
suspend fun getRemoteActivationStatus(
|
||||
@Header("Authorization") authHeader: String,
|
||||
): CardActivationRemoteStateResponse
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ import com.tangem.datasource.api.common.config.*
|
|||
import com.tangem.datasource.api.common.config.Express
|
||||
import com.tangem.datasource.api.common.config.StakeKit
|
||||
import com.tangem.datasource.api.common.config.TangemTech
|
||||
import com.tangem.datasource.api.common.visa.TangemVisaAuthProvider
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.lib.auth.ExpressAuthProvider
|
||||
import com.tangem.lib.auth.StakeKitAuthProvider
|
||||
|
|
@ -47,6 +46,5 @@ internal object ApiConfigsModule {
|
|||
|
||||
@Provides
|
||||
@IntoSet
|
||||
fun provideTangemVisaConfig(tangemVisaAuthProvider: TangemVisaAuthProvider): ApiConfig =
|
||||
TangemVisa(tangemVisaAuthProvider)
|
||||
fun provideTangemVisaConfig(): ApiConfig = TangemVisa()
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import com.tangem.domain.visa.model.VisaAuthTokens
|
|||
|
||||
interface VisaAuthTokenStorage {
|
||||
|
||||
suspend fun store(tokens: VisaAuthTokens)
|
||||
suspend fun store(cardId: String, tokens: VisaAuthTokens)
|
||||
|
||||
suspend fun get(): VisaAuthTokens?
|
||||
suspend fun get(cardId: String): VisaAuthTokens?
|
||||
}
|
||||
|
|
@ -10,12 +10,10 @@ import com.tangem.datasource.api.common.config.ApiConfig.Companion.EXTERNAL_BUIL
|
|||
import com.tangem.datasource.api.common.config.ApiConfig.Companion.INTERNAL_BUILD_TYPE
|
||||
import com.tangem.datasource.api.common.config.ApiConfig.Companion.MOCKED_BUILD_TYPE
|
||||
import com.tangem.datasource.api.common.config.ApiConfig.Companion.RELEASE_BUILD_TYPE
|
||||
import com.tangem.datasource.api.common.visa.TangemVisaAuthProvider
|
||||
import com.tangem.lib.auth.ExpressAuthProvider
|
||||
import com.tangem.lib.auth.StakeKitAuthProvider
|
||||
import com.tangem.utils.ProviderSuspend
|
||||
import com.tangem.utils.version.AppVersionProvider
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
|
@ -31,7 +29,6 @@ private val appVersionProvider = mockk<AppVersionProvider>()
|
|||
private val expressAuthProvider = mockk<ExpressAuthProvider>()
|
||||
private val stakeKitAuthProvider = mockk<StakeKitAuthProvider>()
|
||||
private val appAuthProvider = mockk<AuthProvider>()
|
||||
private val visaAuthProvider = mockk<TangemVisaAuthProvider>()
|
||||
|
||||
// Don't forget to add new config !!!
|
||||
private val API_CONFIGS = setOf(
|
||||
|
|
@ -39,7 +36,7 @@ private val API_CONFIGS = setOf(
|
|||
TangemTech(appVersionProvider, appAuthProvider),
|
||||
StakeKit(stakeKitAuthProvider),
|
||||
TangemVisaAuth(),
|
||||
TangemVisa(visaAuthProvider),
|
||||
TangemVisa(),
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
@ -59,7 +56,6 @@ internal class ProdApiConfigsManagerTest(private val model: Model) {
|
|||
every { stakeKitAuthProvider.getApiKey() } returns STAKE_KIT_API_KEY
|
||||
every { appAuthProvider.getCardId() } returns APP_CARD_ID
|
||||
every { appAuthProvider.getCardPublicKey() } returns APP_CARD_PUBLIC_KEY
|
||||
coEvery { visaAuthProvider.getAuthHeader() } returns VISA_AUTH_HEADER
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -84,7 +80,6 @@ internal class ProdApiConfigsManagerTest(private val model: Model) {
|
|||
const val STAKE_KIT_API_KEY = "stake_kit_api_key"
|
||||
const val APP_CARD_ID = "app_card_id"
|
||||
const val APP_CARD_PUBLIC_KEY = "app_public_key"
|
||||
const val VISA_AUTH_HEADER = "Bearer visa_auth_header"
|
||||
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters
|
||||
|
|
@ -198,9 +193,7 @@ internal class ProdApiConfigsManagerTest(private val model: Model) {
|
|||
expected = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.PROD,
|
||||
baseUrl = "https://bff.tangem.com/",
|
||||
headers = mapOf(
|
||||
"Authorization" to ProviderSuspend { VISA_AUTH_HEADER },
|
||||
),
|
||||
headers = mapOf(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,23 +6,29 @@ import com.tangem.domain.visa.model.ActivationOrder
|
|||
import com.tangem.domain.visa.model.VisaActivationRemoteState
|
||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
internal class DefaultVisaActivationRepository @Inject constructor(
|
||||
internal class DefaultVisaActivationRepository @AssistedInject constructor(
|
||||
@Assisted private val cardId: String,
|
||||
private val visaApi: TangemVisaApi,
|
||||
private val dispatcherProvider: CoroutineDispatcherProvider,
|
||||
private val visaActivationStatusConverter: VisaActivationStatusConverter,
|
||||
) : VisaActivationRepository {
|
||||
|
||||
override suspend fun getActivationRemoteState(): VisaActivationRemoteState = withContext(dispatcherProvider.io) {
|
||||
visaActivationStatusConverter.convert(visaApi.getRemoteActivationStatus())
|
||||
visaActivationStatusConverter.convert(visaApi.getRemoteActivationStatus(cardId))
|
||||
// TODO implement refreshing access token if it's expired
|
||||
}
|
||||
|
||||
override suspend fun getActivationOrderToSign(): ActivationOrder {
|
||||
return ActivationOrder("TODO implement")
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : VisaActivationRepository.Factory {
|
||||
override fun create(cardId: String): DefaultVisaActivationRepository
|
||||
}
|
||||
}
|
||||
|
|
@ -38,5 +38,7 @@ internal interface VisaDataBindsModule {
|
|||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindVisaActivationRepository(repository: DefaultVisaActivationRepository): VisaActivationRepository
|
||||
fun bindVisaActivationRepositoryFactory(
|
||||
repository: DefaultVisaActivationRepository.Factory,
|
||||
): VisaActivationRepository.Factory
|
||||
}
|
||||
|
|
@ -8,4 +8,8 @@ interface VisaActivationRepository {
|
|||
suspend fun getActivationRemoteState(): VisaActivationRemoteState
|
||||
|
||||
suspend fun getActivationOrderToSign(): ActivationOrder
|
||||
|
||||
interface Factory {
|
||||
fun create(cardId: String): VisaActivationRepository
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue