Updated on 2026-08-14
This commit is contained in:
parent
6a82ee1600
commit
229dc89bcb
28 changed files with 623 additions and 36 deletions
|
|
@ -51,18 +51,10 @@ internal interface TangemPayDataModule {
|
|||
@Singleton
|
||||
fun bindKycRepository(repository: DefaultKycRepository): KycRepository
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindOnboardingRepository(repository: DefaultOnboardingRepository): OnboardingRepository
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindTangemPayTxHistoryRepository(repository: DefaultTangemPayTxHistoryRepository): TangemPayTxHistoryRepository
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindCardDetailsRepository(repository: DefaultTangemPayCardDetailsRepository): TangemPayCardDetailsRepository
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindTangemPaySwapRepository(repository: DefaultTangemPayWithdrawRepository): TangemPayWithdrawRepository
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.data.pay.di
|
||||
|
||||
import com.tangem.data.pay.repository.MockAwareOnboardingRepository
|
||||
import com.tangem.data.pay.repository.MockAwareTangemPayCardDetailsRepository
|
||||
import com.tangem.domain.pay.repository.OnboardingRepository
|
||||
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface TangemPayDataMockedModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindOnboardingRepository(repository: MockAwareOnboardingRepository): OnboardingRepository
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindCardDetailsRepository(repository: MockAwareTangemPayCardDetailsRepository): TangemPayCardDetailsRepository
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package com.tangem.data.pay.repository
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.right
|
||||
import com.tangem.core.error.UniversalError
|
||||
import com.tangem.datasource.api.common.config.ApiConfig
|
||||
import com.tangem.datasource.api.common.config.ApiEnvironment
|
||||
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
|
||||
import com.tangem.domain.models.pay.TangemPayEligibilityType
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.pay.model.CustomerInfo
|
||||
import com.tangem.domain.pay.repository.OnboardingRepository
|
||||
import com.tangem.domain.visa.error.VisaApiError
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/** In MOCK env skips local-storage / signing enrollment; server calls go to WireMock. */
|
||||
@Singleton
|
||||
internal class MockAwareOnboardingRepository @Inject constructor(
|
||||
private val real: DefaultOnboardingRepository,
|
||||
private val apiConfigsManager: ApiConfigsManager,
|
||||
) : OnboardingRepository {
|
||||
|
||||
private val mockOrderIds: MutableSet<UserWalletId> = ConcurrentHashMap.newKeySet()
|
||||
|
||||
private val isMockMode: Boolean
|
||||
get() = apiConfigsManager
|
||||
.getEnvironmentConfig(ApiConfig.ID.TangemPay)
|
||||
.environment == ApiEnvironment.MOCK
|
||||
|
||||
override suspend fun validateDeeplink(link: String): Either<UniversalError, Boolean> {
|
||||
if (isMockMode) return true.right()
|
||||
return real.validateDeeplink(link)
|
||||
}
|
||||
|
||||
override suspend fun isTangemPayInitialDataProduced(userWalletId: UserWalletId): Boolean {
|
||||
if (isMockMode) return true
|
||||
return real.isTangemPayInitialDataProduced(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun produceInitialData(userWalletId: UserWalletId) {
|
||||
if (isMockMode) return
|
||||
real.produceInitialData(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun getCustomerInfo(userWalletId: UserWalletId): Either<VisaApiError, CustomerInfo> =
|
||||
real.getCustomerInfo(userWalletId)
|
||||
|
||||
override suspend fun createOrder(userWalletId: UserWalletId): Either<VisaApiError, String> {
|
||||
if (isMockMode) {
|
||||
mockOrderIds.add(userWalletId)
|
||||
return MOCK_ORDER_ID.right()
|
||||
}
|
||||
return real.createOrder(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun clearOrderId(userWalletId: UserWalletId) {
|
||||
if (isMockMode) {
|
||||
mockOrderIds.remove(userWalletId)
|
||||
return
|
||||
}
|
||||
real.clearOrderId(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun getOrderId(userWalletId: UserWalletId): String? {
|
||||
if (isMockMode) return MOCK_ORDER_ID.takeIf { userWalletId in mockOrderIds }
|
||||
return real.getOrderId(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun hasTangemPayInWallet(userWalletId: UserWalletId): Either<VisaApiError, Boolean> =
|
||||
real.hasTangemPayInWallet(userWalletId)
|
||||
|
||||
override suspend fun checkCustomerEligibility(): List<TangemPayEligibilityType> {
|
||||
if (isMockMode) return listOf(TangemPayEligibilityType.DETAILS)
|
||||
return real.checkCustomerEligibility()
|
||||
}
|
||||
|
||||
override suspend fun getCustomerEligibility(): List<TangemPayEligibilityType> {
|
||||
if (isMockMode) return listOf(TangemPayEligibilityType.DETAILS)
|
||||
return real.getCustomerEligibility()
|
||||
}
|
||||
|
||||
override fun getSavedCustomerInfo(userWalletId: UserWalletId): CustomerInfo? =
|
||||
real.getSavedCustomerInfo(userWalletId)
|
||||
|
||||
override suspend fun getHideMainOnboardingBanner(userWalletId: UserWalletId): Boolean {
|
||||
if (isMockMode) return false
|
||||
return real.getHideMainOnboardingBanner(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun setHideMainOnboardingBanner(userWalletId: UserWalletId) {
|
||||
if (isMockMode) return
|
||||
real.setHideMainOnboardingBanner(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun disableTangemPay(userWalletId: UserWalletId): Either<VisaApiError, Unit> {
|
||||
if (isMockMode) return Unit.right()
|
||||
return real.disableTangemPay(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun isTangemPayDeactivated(userWalletId: UserWalletId): Boolean {
|
||||
if (isMockMode) return false
|
||||
return real.isTangemPayDeactivated(userWalletId)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val MOCK_ORDER_ID = "mock-order-id"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
package com.tangem.data.pay.repository
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.right
|
||||
import com.tangem.core.error.UniversalError
|
||||
import com.tangem.datasource.api.common.config.ApiConfig
|
||||
import com.tangem.datasource.api.common.config.ApiEnvironment
|
||||
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
|
||||
import com.tangem.domain.models.account.CardDisplayName
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.pay.model.SetPinResult
|
||||
import com.tangem.domain.pay.model.TangemPayCardBalance
|
||||
import com.tangem.domain.pay.model.TangemPayCardDetails
|
||||
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
||||
import com.tangem.domain.visa.model.TangemPayCardFrozenState
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/** In MOCK env short-circuits RSA-encrypted flows (reveal/getPin/setPin) with hardcoded values. */
|
||||
@Singleton
|
||||
internal class MockAwareTangemPayCardDetailsRepository @Inject constructor(
|
||||
private val real: DefaultTangemPayCardDetailsRepository,
|
||||
private val apiConfigsManager: ApiConfigsManager,
|
||||
) : TangemPayCardDetailsRepository {
|
||||
|
||||
private val isMockMode: Boolean
|
||||
get() = apiConfigsManager
|
||||
.getEnvironmentConfig(ApiConfig.ID.TangemPay)
|
||||
.environment == ApiEnvironment.MOCK
|
||||
|
||||
override suspend fun getCardBalance(userWalletId: UserWalletId): Either<UniversalError, TangemPayCardBalance> =
|
||||
real.getCardBalance(userWalletId)
|
||||
|
||||
override suspend fun revealCardDetails(
|
||||
userWalletId: UserWalletId,
|
||||
): Either<UniversalError, TangemPayCardDetails> {
|
||||
if (isMockMode) {
|
||||
return TangemPayCardDetails(
|
||||
pan = MOCK_PAN,
|
||||
cvv = MOCK_CVV,
|
||||
expirationYear = MOCK_EXPIRATION_YEAR,
|
||||
expirationMonth = MOCK_EXPIRATION_MONTH,
|
||||
).right()
|
||||
}
|
||||
return real.revealCardDetails(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun getPin(userWalletId: UserWalletId, cardId: String): Either<UniversalError, String?> {
|
||||
if (isMockMode) return MOCK_PIN.right()
|
||||
return real.getPin(userWalletId, cardId)
|
||||
}
|
||||
|
||||
override suspend fun setPin(userWalletId: UserWalletId, pin: String): Either<UniversalError, SetPinResult> {
|
||||
if (isMockMode) return SetPinResult.SUCCESS.right()
|
||||
return real.setPin(userWalletId, pin)
|
||||
}
|
||||
|
||||
override suspend fun isAddToWalletDone(userWalletId: UserWalletId): Either<UniversalError, Boolean> =
|
||||
real.isAddToWalletDone(userWalletId)
|
||||
|
||||
override suspend fun setAddToWalletAsDone(userWalletId: UserWalletId): Either<UniversalError, Unit> =
|
||||
real.setAddToWalletAsDone(userWalletId)
|
||||
|
||||
override suspend fun freezeCard(
|
||||
userWalletId: UserWalletId,
|
||||
cardId: String,
|
||||
): Either<UniversalError, TangemPayCardFrozenState> = real.freezeCard(userWalletId, cardId)
|
||||
|
||||
override suspend fun unfreezeCard(
|
||||
userWalletId: UserWalletId,
|
||||
cardId: String,
|
||||
): Either<UniversalError, TangemPayCardFrozenState> = real.unfreezeCard(userWalletId, cardId)
|
||||
|
||||
override fun cardFrozenState(cardId: String): Flow<TangemPayCardFrozenState> =
|
||||
real.cardFrozenState(cardId)
|
||||
|
||||
override suspend fun cardFrozenStateSync(cardId: String): TangemPayCardFrozenState? =
|
||||
real.cardFrozenStateSync(cardId)
|
||||
|
||||
override suspend fun updateCardDisplayName(
|
||||
cardId: String,
|
||||
userWalletId: UserWalletId,
|
||||
displayName: CardDisplayName,
|
||||
): Either<UniversalError, Unit> = real.updateCardDisplayName(cardId, userWalletId, displayName)
|
||||
|
||||
override suspend fun updateCardLimit(
|
||||
cardId: String,
|
||||
userWalletId: UserWalletId,
|
||||
limit: String,
|
||||
): Either<UniversalError, Unit> = real.updateCardLimit(cardId, userWalletId, limit)
|
||||
|
||||
private companion object {
|
||||
const val MOCK_PAN = "4242 4242 4242 4242"
|
||||
const val MOCK_CVV = "123"
|
||||
const val MOCK_EXPIRATION_YEAR = "2028"
|
||||
const val MOCK_EXPIRATION_MONTH = "12"
|
||||
const val MOCK_PIN = "1234"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.data.pay.di
|
||||
|
||||
import com.tangem.data.pay.repository.DefaultOnboardingRepository
|
||||
import com.tangem.data.pay.repository.DefaultTangemPayCardDetailsRepository
|
||||
import com.tangem.domain.pay.repository.OnboardingRepository
|
||||
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface TangemPayDataProductionModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindOnboardingRepository(repository: DefaultOnboardingRepository): OnboardingRepository
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindCardDetailsRepository(repository: DefaultTangemPayCardDetailsRepository): TangemPayCardDetailsRepository
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue