Updated on 2026-08-14
This commit is contained in:
commit
92d6e94e11
25 changed files with 318 additions and 1567 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -3,10 +3,10 @@ package com.tangem.tap.domain.moduleMessage.saltPay
|
|||
import android.content.Context
|
||||
import com.tangem.common.module.ModuleMessageConverter
|
||||
import com.tangem.tap.domain.moduleMessage.ConvertedMessage
|
||||
import com.tangem.tap.domain.moduleMessage.saltPay.converter.SaltPayRegistrationErrorConverter
|
||||
import com.tangem.tap.domain.moduleMessage.saltPay.converter.SaltPayActivationErrorConverter
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayModuleError
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayModuleMessage
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -28,7 +28,7 @@ class SaltPayErrorConverter(
|
|||
) : ModuleMessageConverter<SaltPayModuleError, ConvertedMessage?> {
|
||||
|
||||
override fun convert(message: SaltPayModuleError): ConvertedMessage? = when (message) {
|
||||
is SaltPayRegistrationError -> SaltPayRegistrationErrorConverter(context).convert(message)
|
||||
is SaltPayActivationError -> SaltPayActivationErrorConverter(context).convert(message)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,40 +3,40 @@ package com.tangem.tap.domain.moduleMessage.saltPay.converter
|
|||
import android.content.Context
|
||||
import com.tangem.common.module.ModuleMessageConverter
|
||||
import com.tangem.tap.domain.moduleMessage.ConvertedDialogMessage
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
|
||||
import com.tangem.wallet.R
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class SaltPayRegistrationErrorConverter(
|
||||
internal class SaltPayActivationErrorConverter(
|
||||
private val context: Context,
|
||||
) : ModuleMessageConverter<SaltPayRegistrationError, ConvertedDialogMessage?> {
|
||||
) : ModuleMessageConverter<SaltPayActivationError, ConvertedDialogMessage?> {
|
||||
|
||||
override fun convert(message: SaltPayRegistrationError): ConvertedDialogMessage? {
|
||||
val saltPayError = (message as? SaltPayRegistrationError) ?: throw UnsupportedOperationException()
|
||||
override fun convert(message: SaltPayActivationError): ConvertedDialogMessage? {
|
||||
val saltPayError = (message as? SaltPayActivationError) ?: throw UnsupportedOperationException()
|
||||
|
||||
val dialogMessage = when (saltPayError) {
|
||||
SaltPayRegistrationError.NoGas -> {
|
||||
SaltPayActivationError.NoGas -> {
|
||||
ConvertedDialogMessage(
|
||||
title = context.getString(R.string.saltpay_error_no_gas_title),
|
||||
message = context.getString(R.string.saltpay_error_no_gas_message),
|
||||
)
|
||||
}
|
||||
SaltPayRegistrationError.EmptyBackupCardScanned -> {
|
||||
SaltPayActivationError.EmptyBackupCardScanned -> {
|
||||
ConvertedDialogMessage(
|
||||
title = context.getString(R.string.saltpay_error_empty_backup_title),
|
||||
message = context.getString(R.string.saltpay_error_empty_backup_message),
|
||||
)
|
||||
}
|
||||
SaltPayRegistrationError.WeakPin -> {
|
||||
SaltPayActivationError.WeakPin -> {
|
||||
ConvertedDialogMessage(
|
||||
title = context.getString(R.string.saltpay_error_pin_weak_title),
|
||||
message = context.getString(R.string.saltpay_error_pin_weak_message),
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
val errorMessage = if (saltPayError.message == SaltPayRegistrationError.EMPTY_MESSAGE) {
|
||||
val errorMessage = if (saltPayError.message == SaltPayActivationError.EMPTY_MESSAGE) {
|
||||
saltPayError::class.java.simpleName
|
||||
} else {
|
||||
saltPayError.message
|
||||
|
|
@ -78,8 +78,7 @@ class DetailsViewModel(private val store: Store<AppState>) {
|
|||
store.dispatch(DetailsAction.CreateBackup)
|
||||
}
|
||||
SettingsElement.TermsOfService -> {
|
||||
store.dispatch(DisclaimerAction.ShowAcceptedDisclaimer)
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer))
|
||||
store.dispatch(DisclaimerAction.Show())
|
||||
}
|
||||
SettingsElement.TermsOfUse -> {
|
||||
store.dispatch(DetailsAction.ShowDisclaimer)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,17 @@
|
|||
package com.tangem.tap.features.disclaimer.redux
|
||||
|
||||
import com.tangem.common.extensions.VoidCallback
|
||||
import org.rekotlin.Action
|
||||
|
||||
sealed class DisclaimerAction: Action {
|
||||
object AcceptDisclaimer : DisclaimerAction()
|
||||
object ShowAcceptedDisclaimer : DisclaimerAction()
|
||||
sealed class DisclaimerAction : Action {
|
||||
|
||||
data class SetDisclaimerType(
|
||||
val type: DisclaimerType,
|
||||
) : DisclaimerAction()
|
||||
|
||||
data class Show(val onAcceptCallback: VoidCallback? = null) : DisclaimerAction()
|
||||
data class AcceptDisclaimer(val type: DisclaimerType) : DisclaimerAction()
|
||||
|
||||
internal data class UpdateState(val type: DisclaimerType, val accepted: Boolean) : DisclaimerAction()
|
||||
internal data class SetOnAcceptCallback(val onAcceptCallback: VoidCallback? = null) : DisclaimerAction()
|
||||
}
|
||||
|
|
@ -1,28 +1,65 @@
|
|||
package com.tangem.tap.features.disclaimer.redux
|
||||
|
||||
import com.tangem.tap.common.post
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.home.redux.HomeAction
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.store
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.Middleware
|
||||
|
||||
class DisclaimerMiddleware {
|
||||
val disclaimerMiddleware: Middleware<AppState> = { dispatch, state ->
|
||||
{ next ->
|
||||
{ action ->
|
||||
when (action) {
|
||||
is DisclaimerAction.AcceptDisclaimer -> {
|
||||
preferencesStorage.saveDisclaimerAccepted()
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
|
||||
//delayed sending used for better animation
|
||||
post(550) { store.dispatch(HomeAction.ReadCard) }
|
||||
}
|
||||
}
|
||||
state()?.let { handleDisclaimerMiddleware(action, it) }
|
||||
next(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleDisclaimerMiddleware(action: Action, appState: AppState) {
|
||||
val state = appState.disclaimerState
|
||||
|
||||
when (action) {
|
||||
is DisclaimerAction.SetDisclaimerType -> {
|
||||
handleUpdateState = action.type.createUpdateState()
|
||||
}
|
||||
is DisclaimerAction.Show -> {
|
||||
handleUpdateState = state.type.createUpdateState()
|
||||
store.dispatch(DisclaimerAction.SetOnAcceptCallback(action.onAcceptCallback))
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer))
|
||||
}
|
||||
is DisclaimerAction.AcceptDisclaimer -> {
|
||||
action.type.accept()
|
||||
handleUpdateState = action.type.createUpdateState()
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
state.onAcceptCallback?.invoke()
|
||||
store.dispatch(DisclaimerAction.SetOnAcceptCallback(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun DisclaimerType.accept() = when (this) {
|
||||
DisclaimerType.SaltPay -> preferencesStorage.disclaimerPrefStorage.hasSaltPayTosAccepted = true
|
||||
DisclaimerType.Tangem -> preferencesStorage.disclaimerPrefStorage.hasTangemTosAccepted = true
|
||||
}
|
||||
|
||||
fun DisclaimerType.isAccepted(): Boolean = when (this) {
|
||||
DisclaimerType.SaltPay -> preferencesStorage.disclaimerPrefStorage.hasSaltPayTosAccepted
|
||||
DisclaimerType.Tangem -> preferencesStorage.disclaimerPrefStorage.hasTangemTosAccepted
|
||||
}
|
||||
|
||||
private fun DisclaimerType.createUpdateState(): DisclaimerAction.UpdateState {
|
||||
return DisclaimerAction.UpdateState(this, this.isAccepted())
|
||||
}
|
||||
|
||||
private var handleUpdateState: DisclaimerAction.UpdateState = DisclaimerAction.UpdateState(
|
||||
type = DisclaimerType.Tangem,
|
||||
accepted = false,
|
||||
)
|
||||
set(value) {
|
||||
field = value
|
||||
store.dispatch(value)
|
||||
}
|
||||
|
|
@ -13,9 +13,15 @@ private fun internalReduce(action: Action, state: AppState): DisclaimerState {
|
|||
if (action !is DisclaimerAction) return state.disclaimerState
|
||||
|
||||
val disclaimerState = state.disclaimerState
|
||||
|
||||
return when (action) {
|
||||
is DisclaimerAction.AcceptDisclaimer, DisclaimerAction.ShowAcceptedDisclaimer -> {
|
||||
disclaimerState.copy(accepted = true)
|
||||
}
|
||||
is DisclaimerAction.UpdateState -> disclaimerState.copy(
|
||||
type = action.type,
|
||||
accepted = action.accepted,
|
||||
)
|
||||
is DisclaimerAction.SetOnAcceptCallback -> disclaimerState.copy(
|
||||
onAcceptCallback = action.onAcceptCallback,
|
||||
)
|
||||
else -> disclaimerState
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,30 @@
|
|||
package com.tangem.tap.features.disclaimer.redux
|
||||
|
||||
import android.net.Uri
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
import org.rekotlin.StateType
|
||||
|
||||
data class DisclaimerState(
|
||||
val accepted: Boolean = false
|
||||
val accepted: Boolean = false,
|
||||
val type: DisclaimerType = DisclaimerType.Tangem,
|
||||
val onAcceptCallback: VoidCallback? = null,
|
||||
) : StateType
|
||||
|
||||
sealed class DisclaimerType(
|
||||
val uri: Uri,
|
||||
) {
|
||||
object Tangem : DisclaimerType(Uri.parse("https://tangem.com/tangem_tos.html"))
|
||||
object SaltPay : DisclaimerType(Uri.parse("https://tangem.com/soltpay_tos.html"))
|
||||
|
||||
companion object {
|
||||
fun get(scanResponse: ScanResponse): DisclaimerType = get(scanResponse.card)
|
||||
|
||||
fun get(card: Card): DisclaimerType = when {
|
||||
card.isSaltPay -> SaltPay
|
||||
else -> Tangem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -55,25 +55,25 @@ class DisclaimerFragment : Fragment(R.layout.fragment_disclaimer),
|
|||
binding.toolbar.setNavigationOnClickListener {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
}
|
||||
initAndLoadTOS()
|
||||
setOnClickListeners()
|
||||
initViews()
|
||||
}
|
||||
|
||||
private fun initAndLoadTOS() {
|
||||
private fun initViews() {
|
||||
binding.webView.configureSettings()
|
||||
binding.webView.loadUrl("file:///android_asset/tos.html")
|
||||
}
|
||||
|
||||
private fun setOnClickListeners() {
|
||||
binding.btnAccept.setOnClickListener { store.dispatch(DisclaimerAction.AcceptDisclaimer) }
|
||||
}
|
||||
|
||||
override fun newState(state: DisclaimerState) {
|
||||
override fun newState(state: DisclaimerState) = with(binding) {
|
||||
if (activity == null || view == null) return
|
||||
|
||||
if (state.accepted) {
|
||||
binding.halfTransparentOverlay.hide()
|
||||
binding.btnAccept.hide()
|
||||
halfTransparentOverlay.hide()
|
||||
btnAccept.hide()
|
||||
}
|
||||
|
||||
btnAccept.setOnClickListener {
|
||||
store.dispatch(DisclaimerAction.AcceptDisclaimer(state.type))
|
||||
}
|
||||
|
||||
webView.loadUrl(state.type.uri.toString())
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,5 @@ sealed class HomeAction : Action {
|
|||
data class ShouldScanCardOnResume(val shouldScanCard: Boolean) : HomeAction()
|
||||
object Init : HomeAction()
|
||||
|
||||
data class SetTermsOfUseState(val isDisclaimerAccepted: Boolean) : HomeAction()
|
||||
data class ChangeScanCardButtonState(val state: IndeterminateProgressButton) : HomeAction()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ import com.tangem.tap.common.redux.global.GlobalAction
|
|||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.FragmentShareTransition
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerType
|
||||
import com.tangem.tap.features.disclaimer.redux.isAccepted
|
||||
import com.tangem.tap.features.home.BELARUS_COUNTRY_CODE
|
||||
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
|
||||
import com.tangem.tap.features.home.redux.HomeMiddleware.Companion.BUY_WALLET_URL
|
||||
|
|
@ -63,7 +66,6 @@ private fun handleHomeAction(appState: () -> AppState?, action: Action, dispatch
|
|||
is HomeAction.Init -> {
|
||||
store.dispatch(GlobalAction.RestoreAppCurrency)
|
||||
store.dispatch(GlobalAction.ExchangeManager.Init)
|
||||
store.dispatch(HomeAction.SetTermsOfUseState(preferencesStorage.wasDisclaimerAccepted()))
|
||||
store.dispatch(GlobalAction.FetchUserCountry)
|
||||
}
|
||||
is HomeAction.ShouldScanCardOnResume -> {
|
||||
|
|
@ -73,17 +75,16 @@ private fun handleHomeAction(appState: () -> AppState?, action: Action, dispatch
|
|||
}
|
||||
}
|
||||
is HomeAction.ReadCard -> {
|
||||
if (!preferencesStorage.wasDisclaimerAccepted()) {
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer))
|
||||
} else {
|
||||
changeButtonState(ButtonState.PROGRESS)
|
||||
val scanCardAction = GlobalAction.ScanCard(
|
||||
onSuccess = ::onScanSuccess,
|
||||
onFailure = ::onScanFailure,
|
||||
)
|
||||
store.dispatch(HomeAction.ScanInProgress(true))
|
||||
postUiDelayBg(300) { store.dispatch(scanCardAction) }
|
||||
}
|
||||
changeButtonState(ButtonState.PROGRESS)
|
||||
val scanCardAction = GlobalAction.ScanCard(
|
||||
onSuccess = {
|
||||
store.dispatch(HomeAction.ScanInProgress(false))
|
||||
checkForDisclaimer(it, ::onScanSuccess)
|
||||
},
|
||||
onFailure = ::onScanFailure,
|
||||
)
|
||||
store.dispatch(HomeAction.ScanInProgress(true))
|
||||
postUiDelayBg(300) { store.dispatch(scanCardAction) }
|
||||
}
|
||||
is HomeAction.GoToShop -> {
|
||||
when (action.userCountryCode) {
|
||||
|
|
@ -98,12 +99,28 @@ private fun handleHomeAction(appState: () -> AppState?, action: Action, dispatch
|
|||
}
|
||||
}
|
||||
|
||||
private fun checkForDisclaimer(scanResponse: ScanResponse, onDisclaimerAccepted: (ScanResponse) -> Unit) {
|
||||
val disclaimerType = DisclaimerType.get(scanResponse)
|
||||
store.dispatch(DisclaimerAction.SetDisclaimerType(disclaimerType))
|
||||
|
||||
if (disclaimerType.isAccepted()) {
|
||||
onDisclaimerAccepted((scanResponse))
|
||||
} else {
|
||||
changeButtonState(ButtonState.ENABLED)
|
||||
store.dispatch(
|
||||
DisclaimerAction.Show {
|
||||
changeButtonState(ButtonState.PROGRESS)
|
||||
onDisclaimerAccepted(scanResponse)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onScanSuccess(scanResponse: ScanResponse) {
|
||||
val globalState = store.state.globalState
|
||||
val tapWalletManager = globalState.tapWalletManager
|
||||
tapWalletManager.updateConfigManager(scanResponse)
|
||||
|
||||
store.dispatch(HomeAction.ScanInProgress(false))
|
||||
store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse))
|
||||
|
||||
if (scanResponse.isSaltPay()) {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import com.tangem.common.services.Result
|
|||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.domain.common.extensions.successOr
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayRegistrationStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayActivationStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.updateActivationStatus
|
||||
|
||||
/**
|
||||
|
|
@ -21,15 +21,15 @@ class OnboardingSaltPayHelper {
|
|||
return try {
|
||||
val status = manager.updateActivationStatus(
|
||||
amountToClaim = null,
|
||||
step = SaltPayRegistrationStep.None,
|
||||
step = SaltPayActivationStep.None,
|
||||
).successOr { return it }
|
||||
|
||||
val isRegistrationCase = status.step != SaltPayRegistrationStep.Finished
|
||||
val isRegistrationCase = status.step != SaltPayActivationStep.Finished
|
||||
val isBackupCase = scanResponse.card.backupStatus?.isActive == false
|
||||
Result.Success(isRegistrationCase || isBackupCase)
|
||||
} catch (ex: Exception) {
|
||||
Result.Failure(ex)
|
||||
} catch (error: SaltPayRegistrationError) {
|
||||
} catch (error: SaltPayActivationError) {
|
||||
Result.Failure(error)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import com.tangem.common.CardFilter
|
|||
import com.tangem.domain.common.SaltPayWorkaround
|
||||
import com.tangem.tap.common.redux.StateDialog
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayRegistrationStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayActivationStep
|
||||
import org.rekotlin.StateType
|
||||
|
||||
/**
|
||||
|
|
@ -51,15 +51,15 @@ data class OnboardingWalletState(
|
|||
}
|
||||
step == OnboardingWalletStep.SaltPay && isSaltPay -> {
|
||||
when (onboardingSaltPayState!!.step) {
|
||||
SaltPayRegistrationStep.None, SaltPayRegistrationStep.NoGas -> 0
|
||||
SaltPayRegistrationStep.NeedPin -> 7
|
||||
SaltPayRegistrationStep.CardRegistration -> 8
|
||||
SaltPayRegistrationStep.KycIntro, SaltPayRegistrationStep.KycStart,
|
||||
SaltPayRegistrationStep.KycWaiting, SaltPayRegistrationStep.KycReject,
|
||||
SaltPayActivationStep.None, SaltPayActivationStep.NoGas -> 0
|
||||
SaltPayActivationStep.NeedPin -> 7
|
||||
SaltPayActivationStep.CardRegistration -> 8
|
||||
SaltPayActivationStep.KycIntro, SaltPayActivationStep.KycStart,
|
||||
SaltPayActivationStep.KycWaiting, SaltPayActivationStep.KycReject,
|
||||
-> 9
|
||||
SaltPayRegistrationStep.Claim -> 10
|
||||
SaltPayRegistrationStep.ClaimInProgress -> 11
|
||||
SaltPayRegistrationStep.Finished -> getMaxProgress()
|
||||
SaltPayActivationStep.Claim -> 10
|
||||
SaltPayActivationStep.ClaimInProgress -> 11
|
||||
SaltPayActivationStep.Finished -> getMaxProgress()
|
||||
}
|
||||
}
|
||||
step == OnboardingWalletStep.Done -> getMaxProgress()
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ import com.tangem.operations.attestation.AttestWalletKeyResponse
|
|||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.domain.getFirstToken
|
||||
import com.tangem.tap.domain.tokens.UserWalletId
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
|
||||
import com.tangem.tap.persistence.SaltPayRegistrationStorage
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
|
||||
import com.tangem.tap.persistence.SaltPayActivationStorage
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -34,7 +34,7 @@ class SaltPayActivationManager(
|
|||
private val kycProvider: KYCProvider,
|
||||
private val paymentologyService: PaymentologyApiService,
|
||||
private val gnosisRegistrator: GnosisRegistrator,
|
||||
private val registrationStorage: SaltPayRegistrationStorage,
|
||||
private val registrationStorage: SaltPayActivationStorage,
|
||||
) {
|
||||
val kycUrlProvider = KYCUrlProvider(walletPublicKey, kycProvider)
|
||||
|
||||
|
|
@ -52,9 +52,9 @@ class SaltPayActivationManager(
|
|||
is com.tangem.blockchain.extensions.Result.Success -> if (hasGasResult.data) {
|
||||
Result.Success(Unit)
|
||||
} else {
|
||||
Result.Failure(SaltPayRegistrationError.NoGas)
|
||||
Result.Failure(SaltPayActivationError.NoGas)
|
||||
}
|
||||
is com.tangem.blockchain.extensions.Result.Failure -> Result.Failure(SaltPayRegistrationError.NoGas)
|
||||
is com.tangem.blockchain.extensions.Result.Failure -> Result.Failure(SaltPayActivationError.NoGas)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -70,10 +70,10 @@ class SaltPayActivationManager(
|
|||
|
||||
return try {
|
||||
if (!registrationResponse.success || registrationResponse.results.isEmpty()) {
|
||||
throw SaltPayRegistrationError.EmptyResponse(registrationResponse.error)
|
||||
throw SaltPayActivationError.EmptyResponse(registrationResponse.error)
|
||||
}
|
||||
Result.Success(registrationResponse.results[0])
|
||||
} catch (ex: SaltPayRegistrationError) {
|
||||
} catch (ex: SaltPayActivationError) {
|
||||
Result.Failure(ex)
|
||||
}
|
||||
}
|
||||
|
|
@ -114,11 +114,11 @@ class SaltPayActivationManager(
|
|||
|
||||
suspend fun getAmountToClaim(): Result<Amount> {
|
||||
val amount = gnosisRegistrator.getAllowance().successOr {
|
||||
return Result.Failure(SaltPayRegistrationError.FailedToGetFundsToClaim)
|
||||
return Result.Failure(SaltPayActivationError.FailedToGetFundsToClaim)
|
||||
}
|
||||
|
||||
return if (amount.value == null || amount.value?.isZero() == true) {
|
||||
Result.Failure(SaltPayRegistrationError.NoFundsToClaim)
|
||||
Result.Failure(SaltPayActivationError.NoFundsToClaim)
|
||||
} else {
|
||||
Result.Success(amount)
|
||||
}
|
||||
|
|
@ -126,7 +126,7 @@ class SaltPayActivationManager(
|
|||
|
||||
suspend fun claim(amountToClaim: BigDecimal, signer: TransactionSigner): Result<Unit> {
|
||||
val result = gnosisRegistrator.transferFrom(amountToClaim, signer).successOr {
|
||||
return Result.Failure(SaltPayRegistrationError.ClaimTransactionFailed)
|
||||
return Result.Failure(SaltPayActivationError.ClaimTransactionFailed)
|
||||
}
|
||||
return Result.Success(Unit)
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ class SaltPayActivationManager(
|
|||
kycProvider = SaltPayConfig.stub().kycProvider,
|
||||
paymentologyService = PaymentologyApiService.stub(),
|
||||
gnosisRegistrator = GnosisRegistrator.stub(),
|
||||
registrationStorage = SaltPayRegistrationStorage.stub(),
|
||||
registrationStorage = SaltPayActivationStorage.stub(),
|
||||
cardId = "",
|
||||
cardPublicKey = byteArrayOf(),
|
||||
walletPublicKey = byteArrayOf(),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.tangem.common.core.TangemSdkError
|
|||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.redux.AppDialog
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.SaltPayDialog
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
|
||||
import com.tangem.tap.store
|
||||
|
||||
/**
|
||||
|
|
@ -14,9 +14,9 @@ class SaltPayExceptionHandler {
|
|||
companion object {
|
||||
fun handle(throwable: Throwable) {
|
||||
when (throwable) {
|
||||
is SaltPayRegistrationError -> {
|
||||
is SaltPayActivationError -> {
|
||||
val dialog = when (throwable) {
|
||||
is SaltPayRegistrationError.NoGas -> SaltPayDialog.Activation.NoGas
|
||||
is SaltPayActivationError.NoGas -> SaltPayDialog.Activation.NoGas
|
||||
else -> SaltPayDialog.Activation.OnError(throwable)
|
||||
}
|
||||
store.dispatchDialogShow(dialog)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog
|
|||
|
||||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.tap.common.redux.StateDialog
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -10,7 +10,7 @@ import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPa
|
|||
sealed class SaltPayDialog : StateDialog {
|
||||
sealed class Activation : SaltPayDialog() {
|
||||
object NoGas : SaltPayDialog()
|
||||
data class OnError(val error: SaltPayRegistrationError) : SaltPayDialog()
|
||||
data class OnError(val error: SaltPayActivationError) : SaltPayDialog()
|
||||
data class TryToInterrupt(val onOk: VoidCallback, val onCancel: VoidCallback) : SaltPayDialog()
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ sealed class SaltPayModuleError(
|
|||
}
|
||||
}
|
||||
|
||||
sealed class SaltPayRegistrationError(
|
||||
sealed class SaltPayActivationError(
|
||||
subCode: Int,
|
||||
message: String? = null,
|
||||
override val data: Any? = null,
|
||||
|
|
@ -28,27 +28,27 @@ sealed class SaltPayRegistrationError(
|
|||
subCode = ERROR_CODE_REGISTRATION + subCode,
|
||||
message = message ?: EMPTY_MESSAGE,
|
||||
) {
|
||||
object Unknown : SaltPayRegistrationError(4)
|
||||
object Empty : SaltPayRegistrationError(4)
|
||||
object Unknown : SaltPayActivationError(4)
|
||||
object Empty : SaltPayActivationError(4)
|
||||
|
||||
// gnosis
|
||||
object FailedToMakeTxData : SaltPayRegistrationError(1)
|
||||
object FailedToSendTx : SaltPayRegistrationError(2)
|
||||
object FailedToMakeTxData : SaltPayActivationError(1)
|
||||
object FailedToSendTx : SaltPayActivationError(2)
|
||||
|
||||
object NeedPin : SaltPayRegistrationError(3)
|
||||
object NoGas : SaltPayRegistrationError(5) //
|
||||
class EmptyResponse(message: String?) : SaltPayRegistrationError(6, message)
|
||||
class CardNotFound(message: String?) : SaltPayRegistrationError(8, message)
|
||||
class CardDisabled(message: String?) : SaltPayRegistrationError(9, message)
|
||||
class CardNotPassed(message: String?) : SaltPayRegistrationError(10, message)
|
||||
object EmptyDynamicAttestResponse : SaltPayRegistrationError(11)
|
||||
object EmptyBackupCardScanned : SaltPayRegistrationError(12)
|
||||
object WeakPin : SaltPayRegistrationError(13)
|
||||
object NeedPin : SaltPayActivationError(3)
|
||||
object NoGas : SaltPayActivationError(5) //
|
||||
class EmptyResponse(message: String?) : SaltPayActivationError(6, message)
|
||||
class CardNotFound(message: String?) : SaltPayActivationError(8, message)
|
||||
class CardDisabled(message: String?) : SaltPayActivationError(9, message)
|
||||
class CardNotPassed(message: String?) : SaltPayActivationError(10, message)
|
||||
object EmptyDynamicAttestResponse : SaltPayActivationError(11)
|
||||
object EmptyBackupCardScanned : SaltPayActivationError(12)
|
||||
object WeakPin : SaltPayActivationError(13)
|
||||
|
||||
object FailedToGetFundsToClaim : SaltPayRegistrationError(14)
|
||||
object NoFundsToClaim : SaltPayRegistrationError(15)
|
||||
object ClaimTransactionFailed : SaltPayRegistrationError(16)
|
||||
object NotClaimed : SaltPayRegistrationError(17)
|
||||
object FailedToGetFundsToClaim : SaltPayActivationError(14)
|
||||
object NoFundsToClaim : SaltPayActivationError(15)
|
||||
object ClaimTransactionFailed : SaltPayActivationError(16)
|
||||
object NotClaimed : SaltPayActivationError(17)
|
||||
|
||||
companion object {
|
||||
const val EMPTY_MESSAGE = ""
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ sealed class OnboardingSaltPayAction : Action {
|
|||
data class TrySetPin(val pin: String) : OnboardingSaltPayAction()
|
||||
data class SetPin(val pin: String) : OnboardingSaltPayAction()
|
||||
|
||||
data class SetStep(val newStep: SaltPayRegistrationStep? = null) : OnboardingSaltPayAction()
|
||||
data class SetStep(val newStep: SaltPayActivationStep? = null) : OnboardingSaltPayAction()
|
||||
data class SetAmountToClaim(val amount: Amount?) : OnboardingSaltPayAction()
|
||||
data class SetTokenBalance(val balanceValue: BigDecimal) : OnboardingSaltPayAction()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWallet
|
|||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.AllSymbolsTheSameFilter
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayExceptionHandler
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdk
|
||||
|
|
@ -89,7 +89,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
}
|
||||
|
||||
val pinCode = state.pinCode.guard {
|
||||
onError(SaltPayRegistrationError.NeedPin)
|
||||
onError(SaltPayActivationError.NeedPin)
|
||||
return@launch
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
}
|
||||
|
||||
if (!attestationResponse.success) {
|
||||
onError(SaltPayRegistrationError.CardNotFound(attestationResponse.error))
|
||||
onError(SaltPayActivationError.CardNotFound(attestationResponse.error))
|
||||
return@launch
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
}
|
||||
|
||||
saltPayManager.sendTransactions(registrationResponse.signedTransactions).successOr {
|
||||
onError(SaltPayRegistrationError.FailedToSendTx)
|
||||
onError(SaltPayActivationError.FailedToSendTx)
|
||||
return@launch
|
||||
}
|
||||
|
||||
|
|
@ -128,12 +128,12 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
|
||||
withMainContext {
|
||||
handleInProgress = false
|
||||
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.KycIntro))
|
||||
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycIntro))
|
||||
}
|
||||
}
|
||||
}
|
||||
is OnboardingSaltPayAction.OpenUtorgKYC -> {
|
||||
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.KycStart))
|
||||
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycStart))
|
||||
}
|
||||
is OnboardingSaltPayAction.UtorgKYCRedirectSuccess -> {
|
||||
store.dispatch(OnboardingSaltPayAction.RegisterKYC)
|
||||
|
|
@ -155,8 +155,8 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
try {
|
||||
assertPinValid(action.pin, getState().pinLength)
|
||||
store.dispatch(OnboardingSaltPayAction.SetPin(action.pin))
|
||||
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.CardRegistration))
|
||||
} catch (error: SaltPayRegistrationError) {
|
||||
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.CardRegistration))
|
||||
} catch (error: SaltPayActivationError) {
|
||||
SaltPayExceptionHandler.handle(error)
|
||||
}
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
|
||||
scope.launch {
|
||||
val amountToClaim = getAmountToClaimIfNeeded(state.saltPayManager, state.amountToClaim).guard {
|
||||
onException(SaltPayRegistrationError.NoFundsToClaim)
|
||||
onException(SaltPayActivationError.NoFundsToClaim)
|
||||
return@launch
|
||||
}
|
||||
|
||||
|
|
@ -187,12 +187,12 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
)
|
||||
}
|
||||
state.saltPayManager.claim(amountToClaim.value!!, signer).successOr {
|
||||
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.Claim))
|
||||
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.Claim))
|
||||
onException(it.error)
|
||||
return@launch
|
||||
}
|
||||
|
||||
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.ClaimInProgress))
|
||||
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.ClaimInProgress))
|
||||
dispatchOnMain(OnboardingSaltPayAction.RefreshClaim)
|
||||
}
|
||||
}
|
||||
|
|
@ -211,7 +211,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
handleInProgress = false
|
||||
handleClaimRefreshInProgress = false
|
||||
dispatchOnMain(OnboardingSaltPayAction.SetTokenBalance(balance))
|
||||
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.Finished))
|
||||
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.Finished))
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
|
|
@ -221,13 +221,13 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
}
|
||||
|
||||
data class UpdateResult(
|
||||
val step: SaltPayRegistrationStep = SaltPayRegistrationStep.None,
|
||||
val step: SaltPayActivationStep = SaltPayActivationStep.None,
|
||||
val amountToClaim: Amount? = null,
|
||||
)
|
||||
|
||||
suspend fun SaltPayActivationManager.updateActivationStatus(
|
||||
amountToClaim: Amount?,
|
||||
step: SaltPayRegistrationStep,
|
||||
step: SaltPayActivationStep,
|
||||
): Result<UpdateResult> {
|
||||
Timber.d("updateSaltPayStatus")
|
||||
var updateResult = UpdateResult()
|
||||
|
|
@ -248,9 +248,9 @@ suspend fun SaltPayActivationManager.updateActivationStatus(
|
|||
val fetchedAmountToClaim = getAmountToClaimIfNeeded(this, amountToClaim)
|
||||
updateResult = when {
|
||||
// if fetchedAmountToClaim = null -> then it already claimed
|
||||
saltPayStep == SaltPayRegistrationStep.Claim && fetchedAmountToClaim == null -> {
|
||||
saltPayStep == SaltPayActivationStep.Claim && fetchedAmountToClaim == null -> {
|
||||
updateResult.copy(
|
||||
step = SaltPayRegistrationStep.Finished,
|
||||
step = SaltPayActivationStep.Finished,
|
||||
amountToClaim = fetchedAmountToClaim,
|
||||
)
|
||||
}
|
||||
|
|
@ -298,7 +298,7 @@ private var handleInProgress: Boolean = false
|
|||
store.dispatchOnMain(OnboardingSaltPayAction.SetInProgress(value))
|
||||
}
|
||||
|
||||
private suspend fun onError(error: SaltPayRegistrationError) {
|
||||
private suspend fun onError(error: SaltPayActivationError) {
|
||||
withMainContext {
|
||||
handleInProgress = false
|
||||
SaltPayExceptionHandler.handle(error)
|
||||
|
|
@ -314,12 +314,12 @@ private suspend fun onException(error: Throwable) {
|
|||
|
||||
private suspend fun checkGasIfNeeded(
|
||||
saltPayManager: SaltPayActivationManager,
|
||||
step: SaltPayRegistrationStep,
|
||||
step: SaltPayActivationStep,
|
||||
): Result<Unit> {
|
||||
Timber.d("checkGasIfNeeded: for step: %s", step)
|
||||
if (step == SaltPayRegistrationStep.KycStart ||
|
||||
step == SaltPayRegistrationStep.KycWaiting ||
|
||||
step == SaltPayRegistrationStep.Finished
|
||||
if (step == SaltPayActivationStep.KycStart ||
|
||||
step == SaltPayActivationStep.KycWaiting ||
|
||||
step == SaltPayActivationStep.Finished
|
||||
) {
|
||||
Timber.d("checkGasIfNeeded: no need to check for step: %s", step)
|
||||
return Result.Success(Unit)
|
||||
|
|
@ -335,17 +335,17 @@ private suspend fun checkGasIfNeeded(
|
|||
|
||||
private suspend fun registerKYCIfNeeded(
|
||||
saltPayManager: SaltPayActivationManager,
|
||||
step: SaltPayRegistrationStep,
|
||||
step: SaltPayActivationStep,
|
||||
): Result<Unit> {
|
||||
Timber.d("registerKYCIfNeeded: step: %s", step)
|
||||
if (step != SaltPayRegistrationStep.KycStart) {
|
||||
if (step != SaltPayActivationStep.KycStart) {
|
||||
Timber.d("registerKYCIfNeeded: return Success, because step != KycStart")
|
||||
return Result.Success(Unit)
|
||||
}
|
||||
|
||||
withMainContext {
|
||||
Timber.d("registerKYCIfNeeded: set new step: KycWaiting")
|
||||
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.KycWaiting))
|
||||
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycWaiting))
|
||||
}
|
||||
|
||||
Timber.d("saltPayManager.registerKYC()")
|
||||
|
|
@ -354,7 +354,7 @@ private suspend fun registerKYCIfNeeded(
|
|||
|
||||
private suspend fun checkRegistration(
|
||||
saltPayManager: SaltPayActivationManager,
|
||||
): Result<SaltPayRegistrationStep> {
|
||||
): Result<SaltPayActivationStep> {
|
||||
Timber.d("checkRegistration")
|
||||
return try {
|
||||
val registrationResponseItem = saltPayManager.checkRegistration().successOr {
|
||||
|
|
@ -366,51 +366,51 @@ private suspend fun checkRegistration(
|
|||
val step = registrationResponseItem.toSaltPayStep()
|
||||
Timber.d("checkRegistration: step: %s", step)
|
||||
Result.Success(step)
|
||||
} catch (ex: SaltPayRegistrationError) {
|
||||
} catch (ex: SaltPayActivationError) {
|
||||
Timber.e(ex, "checkRegistration: step")
|
||||
Result.Failure(ex)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(SaltPayRegistrationError::class)
|
||||
fun RegistrationResponse.Item.toSaltPayStep(): SaltPayRegistrationStep {
|
||||
@Throws(SaltPayActivationError::class)
|
||||
fun RegistrationResponse.Item.toSaltPayStep(): SaltPayActivationStep {
|
||||
return when {
|
||||
passed != true -> throw SaltPayRegistrationError.CardNotPassed(this.error)
|
||||
disabledByAdmin == true -> throw SaltPayRegistrationError.CardDisabled(this.error)
|
||||
passed != true -> throw SaltPayActivationError.CardNotPassed(this.error)
|
||||
disabledByAdmin == true -> throw SaltPayActivationError.CardDisabled(this.error)
|
||||
|
||||
// go to claim screen
|
||||
active == true -> SaltPayRegistrationStep.Claim
|
||||
active == true -> SaltPayActivationStep.Claim
|
||||
|
||||
// pinSet is false, go toPin screen
|
||||
pinSet == false -> SaltPayRegistrationStep.NeedPin
|
||||
pinSet == false -> SaltPayActivationStep.NeedPin
|
||||
|
||||
kycStatus != null -> {
|
||||
when (kycStatus) {
|
||||
KYCStatus.NOT_STARTED, KYCStatus.STARTED -> SaltPayRegistrationStep.KycStart
|
||||
KYCStatus.WAITING_FOR_APPROVAL -> SaltPayRegistrationStep.KycWaiting
|
||||
KYCStatus.CORRECTION_REQUESTED, KYCStatus.REJECTED -> SaltPayRegistrationStep.KycReject
|
||||
KYCStatus.APPROVED -> SaltPayRegistrationStep.Claim
|
||||
KYCStatus.NOT_STARTED, KYCStatus.STARTED -> SaltPayActivationStep.KycStart
|
||||
KYCStatus.WAITING_FOR_APPROVAL -> SaltPayActivationStep.KycWaiting
|
||||
KYCStatus.CORRECTION_REQUESTED, KYCStatus.REJECTED -> SaltPayActivationStep.KycReject
|
||||
KYCStatus.APPROVED -> SaltPayActivationStep.Claim
|
||||
null -> throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
// kycDate is set, go to kyc waiting screen
|
||||
kycDate != null -> SaltPayRegistrationStep.KycWaiting
|
||||
kycDate != null -> SaltPayActivationStep.KycWaiting
|
||||
|
||||
else -> SaltPayRegistrationStep.KycIntro
|
||||
else -> SaltPayActivationStep.KycIntro
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(SaltPayRegistrationError::class)
|
||||
@Throws(SaltPayActivationError::class)
|
||||
private fun assertPinValid(pin: String, pinLength: Int) {
|
||||
val array = pin.toCharArray()
|
||||
|
||||
if (array.size < pinLength) throw SaltPayRegistrationError.WeakPin
|
||||
if (array.size < pinLength) throw SaltPayActivationError.WeakPin
|
||||
|
||||
val filters: List<Filter<String>> = listOf(
|
||||
AllSymbolsTheSameFilter(),
|
||||
)
|
||||
|
||||
if (filters.any { it.filter(pin) }) {
|
||||
throw SaltPayRegistrationError.WeakPin
|
||||
throw SaltPayActivationError.WeakPin
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ import com.tangem.tap.features.onboarding.products.wallet.saltPay.KYCProvider
|
|||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayConfig
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.persistence.SaltPayRegistrationStorage
|
||||
import com.tangem.tap.persistence.SaltPayActivationStorage
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.store
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -33,7 +33,7 @@ data class OnboardingSaltPayState(
|
|||
val accessCode: String? = null,
|
||||
val amountToClaim: Amount? = null,
|
||||
val tokenAmount: Amount = Amount(SaltPayWorkaround.tokenFrom(Blockchain.SaltPay), BigDecimal.ZERO),
|
||||
val step: SaltPayRegistrationStep = SaltPayRegistrationStep.None,
|
||||
val step: SaltPayActivationStep = SaltPayActivationStep.None,
|
||||
val saltPayCardArtworkUrl: String? = null,
|
||||
val inProgress: Boolean = false,
|
||||
val claimInProgress: Boolean = false,
|
||||
|
|
@ -60,7 +60,7 @@ data class OnboardingSaltPayState(
|
|||
scanResponse = scanResponse,
|
||||
gnosisRegistrator = gnosisRegistrator,
|
||||
paymentologyService = store.state.domainNetworks.paymentologyService,
|
||||
registrationStorage = preferencesStorage.saltPayRegistrationStorage,
|
||||
registrationStorage = preferencesStorage.saltPayActivationStorage,
|
||||
kycProvider = saltPayConfig.kycProvider,
|
||||
)
|
||||
test(scanResponse, gnosisRegistrator)
|
||||
|
|
@ -83,7 +83,7 @@ data class OnboardingSaltPayState(
|
|||
scanResponse: ScanResponse,
|
||||
gnosisRegistrator: GnosisRegistrator,
|
||||
paymentologyService: PaymentologyApiService,
|
||||
registrationStorage: SaltPayRegistrationStorage,
|
||||
registrationStorage: SaltPayActivationStorage,
|
||||
kycProvider: KYCProvider,
|
||||
): SaltPayActivationManager {
|
||||
if (!scanResponse.isSaltPay()) {
|
||||
|
|
@ -115,7 +115,7 @@ data class OnboardingSaltPayState(
|
|||
}
|
||||
}
|
||||
|
||||
enum class SaltPayRegistrationStep {
|
||||
enum class SaltPayActivationStep {
|
||||
None,
|
||||
NoGas,
|
||||
NeedPin,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ import com.tangem.tap.features.onboarding.products.wallet.saltPay.UtorgWebViewCl
|
|||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.SaltPayDialog
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayRegistrationStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayActivationStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.ui.OnboardingWalletFragment
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -67,7 +67,7 @@ internal class OnboardingSaltPayView(
|
|||
}
|
||||
|
||||
private var progressButton: SaltPayProgressButton? = null
|
||||
private var previousStep: SaltPayRegistrationStep = SaltPayRegistrationStep.None
|
||||
private var previousStep: SaltPayActivationStep = SaltPayActivationStep.None
|
||||
|
||||
fun newState(state: OnboardingWalletState) {
|
||||
handleCardArtworks(state)
|
||||
|
|
@ -133,16 +133,16 @@ internal class OnboardingSaltPayView(
|
|||
walletFragment.bindingSaltPay.onboardingSaltpayContainer.show()
|
||||
|
||||
when (state.step) {
|
||||
SaltPayRegistrationStep.NoGas -> handleNoGas()
|
||||
SaltPayRegistrationStep.NeedPin -> handleNeedPin()
|
||||
SaltPayRegistrationStep.CardRegistration -> handleCardRegistration()
|
||||
SaltPayRegistrationStep.KycIntro -> handleKycIntro()
|
||||
SaltPayRegistrationStep.KycStart -> handleKycStart(state)
|
||||
SaltPayRegistrationStep.KycWaiting -> handleKycWaiting()
|
||||
SaltPayRegistrationStep.KycReject -> handleKycReject()
|
||||
SaltPayRegistrationStep.Claim -> handleClaim(state)
|
||||
SaltPayRegistrationStep.ClaimInProgress -> handleClaim(state)
|
||||
SaltPayRegistrationStep.Finished -> handleClaim(state)
|
||||
SaltPayActivationStep.NoGas -> handleNoGas()
|
||||
SaltPayActivationStep.NeedPin -> handleNeedPin()
|
||||
SaltPayActivationStep.CardRegistration -> handleCardRegistration()
|
||||
SaltPayActivationStep.KycIntro -> handleKycIntro()
|
||||
SaltPayActivationStep.KycStart -> handleKycStart(state)
|
||||
SaltPayActivationStep.KycWaiting -> handleKycWaiting()
|
||||
SaltPayActivationStep.KycReject -> handleKycReject()
|
||||
SaltPayActivationStep.Claim -> handleClaim(state)
|
||||
SaltPayActivationStep.ClaimInProgress -> handleClaim(state)
|
||||
SaltPayActivationStep.Finished -> handleClaim(state)
|
||||
}
|
||||
progressButton?.changeState(state.mainButtonState)
|
||||
}
|
||||
|
|
@ -276,7 +276,7 @@ internal class OnboardingSaltPayView(
|
|||
topContainer.onboardingTvBalance.tvBalanceCurrency.text = ""
|
||||
|
||||
when (state.step) {
|
||||
SaltPayRegistrationStep.Claim -> {
|
||||
SaltPayActivationStep.Claim -> {
|
||||
btnRefreshBalanceWidget.mainView.hide()
|
||||
claimValueString(state)?.let {
|
||||
tvHeader.text = getString(R.string.onboarding_title_claim, it)
|
||||
|
|
@ -288,13 +288,13 @@ internal class OnboardingSaltPayView(
|
|||
store.dispatch(OnboardingSaltPayAction.Claim)
|
||||
}
|
||||
}
|
||||
SaltPayRegistrationStep.ClaimInProgress -> {
|
||||
SaltPayActivationStep.ClaimInProgress -> {
|
||||
btnRefreshBalanceWidget.mainView.show()
|
||||
tvHeader.text = getString(R.string.onboarding_title_claim_progress)
|
||||
tvBody.text = getString(R.string.onboarding_subtitle_claim_progress)
|
||||
btnMain.text = getString(R.string.onboarding_button_claim)
|
||||
}
|
||||
SaltPayRegistrationStep.Finished -> {
|
||||
SaltPayActivationStep.Finished -> {
|
||||
tvHeader.setText(R.string.common_success)
|
||||
tvBody.setText(R.string.onboarding_subtitle_success_claim)
|
||||
|
||||
|
|
@ -329,7 +329,7 @@ internal class OnboardingSaltPayView(
|
|||
)
|
||||
}
|
||||
|
||||
private fun updateConstraints(currentStep: SaltPayRegistrationStep, @LayoutRes layoutId: Int) {
|
||||
private fun updateConstraints(currentStep: SaltPayActivationStep, @LayoutRes layoutId: Int) {
|
||||
if (this.previousStep == currentStep) return
|
||||
|
||||
with(claimBinding.onboardingTopContainer) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
package com.tangem.tap.persistence
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class DisclaimerPrefStorage(
|
||||
private val preferences: SharedPreferences,
|
||||
) {
|
||||
|
||||
var hasTangemTosAccepted: Boolean
|
||||
get() = preferences.getBoolean(KEY_TANGEM_TOS, false)
|
||||
set(value) = preferences.edit { putBoolean(KEY_TANGEM_TOS, value) }
|
||||
|
||||
var hasSaltPayTosAccepted: Boolean
|
||||
get() = preferences.getBoolean(KEY_SALT_PAY_TOS, false)
|
||||
set(value) = preferences.edit { putBoolean(KEY_SALT_PAY_TOS, value) }
|
||||
|
||||
companion object {
|
||||
private const val KEY_TANGEM_TOS = "tangem_tos_accepted"
|
||||
private const val KEY_SALT_PAY_TOS = "saltPay_tos_accepted"
|
||||
}
|
||||
}
|
||||
|
|
@ -7,15 +7,16 @@ import androidx.core.content.edit
|
|||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import java.util.*
|
||||
|
||||
|
||||
class PreferencesStorage(applicationContext: Application) {
|
||||
|
||||
private val preferences: SharedPreferences = applicationContext.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)
|
||||
private val preferences: SharedPreferences =
|
||||
applicationContext.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)
|
||||
|
||||
val appRatingLaunchObserver: AppRatingLaunchObserver
|
||||
val usedCardsPrefStorage: UsedCardsPrefStorage
|
||||
val fiatCurrenciesPrefStorage: FiatCurrenciesPrefStorage
|
||||
val saltPayRegistrationStorage: SaltPayRegistrationStorage
|
||||
val saltPayActivationStorage: SaltPayActivationStorage
|
||||
val disclaimerPrefStorage: DisclaimerPrefStorage
|
||||
|
||||
init {
|
||||
incrementLaunchCounter()
|
||||
|
|
@ -24,7 +25,8 @@ class PreferencesStorage(applicationContext: Application) {
|
|||
usedCardsPrefStorage.migrate()
|
||||
fiatCurrenciesPrefStorage = FiatCurrenciesPrefStorage(preferences, MoshiJsonConverter.INSTANCE)
|
||||
fiatCurrenciesPrefStorage.migrate()
|
||||
saltPayRegistrationStorage = SaltPayRegistrationPrefStorage(applicationContext, MoshiJsonConverter.INSTANCE)
|
||||
saltPayActivationStorage = SaltPayActivationPrefStorage(applicationContext, MoshiJsonConverter.INSTANCE)
|
||||
disclaimerPrefStorage = DisclaimerPrefStorage(preferences)
|
||||
}
|
||||
|
||||
var chatFirstLaunchTime: Long?
|
||||
|
|
@ -38,14 +40,6 @@ class PreferencesStorage(applicationContext: Application) {
|
|||
return usedCardsPrefStorage.wasScanned(cardId)
|
||||
}
|
||||
|
||||
fun saveDisclaimerAccepted() {
|
||||
preferences.edit { putBoolean(DISCLAIMER_ACCEPTED_KEY, true) }
|
||||
}
|
||||
|
||||
fun wasDisclaimerAccepted(): Boolean {
|
||||
return preferences.getBoolean(DISCLAIMER_ACCEPTED_KEY, false)
|
||||
}
|
||||
|
||||
fun saveTwinsOnboardingShown() {
|
||||
preferences.edit { putBoolean(TWINS_ONBOARDING_SHOWN_KEY, true) }
|
||||
}
|
||||
|
|
@ -61,12 +55,10 @@ class PreferencesStorage(applicationContext: Application) {
|
|||
|
||||
companion object {
|
||||
private const val PREFERENCES_NAME = "tapPrefs"
|
||||
private const val DISCLAIMER_ACCEPTED_KEY = "disclaimerAccepted"
|
||||
private const val TWINS_ONBOARDING_SHOWN_KEY = "twinsOnboardingShown"
|
||||
private const val APP_LAUNCH_COUNT_KEY = "launchCount"
|
||||
private const val CHAT_FIRST_LAUNCH_KEY = "chatFirstLaunchKey"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class AppRatingLaunchObserver(
|
||||
|
|
|
|||
|
|
@ -10,27 +10,27 @@ import com.tangem.tangem_sdk_new.storage.createEncryptedSharedPreferences
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface SaltPayRegistrationStorage {
|
||||
var data: SaltPayRegistratorData
|
||||
interface SaltPayActivationStorage {
|
||||
var data: SaltPayActivationData
|
||||
|
||||
fun reset()
|
||||
|
||||
companion object {
|
||||
fun stub(): SaltPayRegistrationStorage = object : SaltPayRegistrationStorage {
|
||||
override var data: SaltPayRegistratorData = SaltPayRegistratorData()
|
||||
fun stub(): SaltPayActivationStorage = object : SaltPayActivationStorage {
|
||||
override var data: SaltPayActivationData = SaltPayActivationData()
|
||||
override fun reset() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class SaltPayRegistratorData(
|
||||
data class SaltPayActivationData(
|
||||
val transactionsSent: Boolean = false,
|
||||
)
|
||||
|
||||
class SaltPayRegistrationPrefStorage(
|
||||
class SaltPayActivationPrefStorage(
|
||||
context: Context,
|
||||
private val converter: MoshiJsonConverter,
|
||||
) : SaltPayRegistrationStorage {
|
||||
) : SaltPayActivationStorage {
|
||||
|
||||
private val storage: ArmadilloSharedPreferences = SecureStorage.createEncryptedSharedPreferences(
|
||||
context = context,
|
||||
|
|
@ -43,7 +43,7 @@ class SaltPayRegistrationPrefStorage(
|
|||
fetch()
|
||||
}
|
||||
|
||||
override var data: SaltPayRegistratorData = SaltPayRegistratorData()
|
||||
override var data: SaltPayActivationData = SaltPayActivationData()
|
||||
set(value) {
|
||||
field = value
|
||||
if (!isFetching) save()
|
||||
|
|
@ -52,7 +52,7 @@ class SaltPayRegistrationPrefStorage(
|
|||
override fun reset() {
|
||||
storage.edit(true) {
|
||||
this.remove(REGISTRATION_DATA_KEY)
|
||||
data = SaltPayRegistratorData()
|
||||
data = SaltPayActivationData()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,14 +62,14 @@ class SaltPayRegistrationPrefStorage(
|
|||
}
|
||||
}
|
||||
|
||||
private fun fetch(): SaltPayRegistratorData {
|
||||
private fun fetch(): SaltPayActivationData {
|
||||
isFetching = true
|
||||
|
||||
val jsonData = storage.getString(REGISTRATION_DATA_KEY, null)
|
||||
data = if (jsonData == null) {
|
||||
SaltPayRegistratorData()
|
||||
SaltPayActivationData()
|
||||
} else {
|
||||
converter.fromJson<SaltPayRegistratorData>(jsonData) ?: SaltPayRegistratorData()
|
||||
converter.fromJson<SaltPayActivationData>(jsonData) ?: SaltPayActivationData()
|
||||
}
|
||||
isFetching = false
|
||||
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
android:layout_height="?attr/actionBarSize"
|
||||
app:navigationIcon="@drawable/ic_baseline_arrow_back_24"
|
||||
app:title="@string/disclaimer_title" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
|
|
@ -31,17 +32,26 @@
|
|||
android:background="@color/white"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<WebView
|
||||
android:id="@+id/web_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="120dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<WebView
|
||||
android:id="@+id/web_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue