diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt index 1147faf13a..a66fd6caa0 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -12,7 +12,6 @@ import com.tangem.tap.features.onboarding.AddressInfoBottomSheetDialog import com.tangem.tap.features.onboarding.OnboardingDialog import com.tangem.tap.features.onboarding.products.twins.ui.dialog.TwinningProcessNotCompletedDialog import com.tangem.tap.features.onboarding.products.wallet.redux.BackupDialog -import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.* import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.* import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.tap.features.wallet.ui.dialogs.* @@ -118,9 +117,6 @@ class DialogManager : StoreSubscriber { context = context, cardId = state.dialog.cardId, ) - is SaltPayDialog.Activation.NoGas -> NoFundsForActivationDialog.create(context) - is SaltPayDialog.Activation.PutVisaCard -> PutVisaCardDialog.create(context) - is SaltPayDialog.Activation.OnError -> RegistrationErrorDialog.create(context, state.dialog) is WalletDialog.CurrencySelectionDialog -> CurrencySelectionDialog.create(state.dialog, context) is WalletDialog.ChooseTradeActionDialog -> ChooseTradeActionBottomSheetDialog(context, state.dialog) is WalletDialog.SelectAmountToSendDialog -> AmountToSendBottomSheetDialog(context, state.dialog) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt index 61d71c5a14..0a7928efd5 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt @@ -3,7 +3,6 @@ package com.tangem.tap.common.analytics.converters import com.tangem.blockchain.common.Blockchain import com.tangem.common.Converter import com.tangem.domain.common.CardTypesResolver -import com.tangem.domain.common.SaltPayWorkaround import com.tangem.tap.common.analytics.events.AnalyticsParam /** @@ -17,7 +16,6 @@ class ParamCardCurrencyConverter : Converter AnalyticsParam.CurrencyType.Blockchain(value.getBlockchain()) value.isTangemTwins() -> AnalyticsParam.CurrencyType.Blockchain(Blockchain.Bitcoin) - value.isSaltPay() -> AnalyticsParam.CurrencyType.Token(SaltPayWorkaround.tokenFrom(Blockchain.SaltPay)) value.getBlockchain() != Blockchain.Unknown -> AnalyticsParam.CurrencyType.Blockchain(value.getBlockchain()) value.getPrimaryToken() != null -> AnalyticsParam.CurrencyType.Token(value.getPrimaryToken()!!) else -> null diff --git a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt index 748a82a14e..864c9dadbb 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt @@ -45,11 +45,6 @@ class CardContextInterceptor( ProductType.Note -> "Note" ProductType.Twins -> "Twin" ProductType.Wallet -> "Wallet" - ProductType.SaltPay -> if (scanResponse.cardTypesResolver.isSaltPayVisa()) { - "Visa" - } else { - "Visa Backup" - } ProductType.Start2Coin -> "Start2Coin" else -> if (DemoHelper.isDemoCard(scanResponse)) { if (DemoHelper.isTestDemoCard(scanResponse)) { diff --git a/app/src/main/java/com/tangem/tap/common/extensions/BackupService.kt b/app/src/main/java/com/tangem/tap/common/extensions/BackupService.kt deleted file mode 100644 index 140f0946b4..0000000000 --- a/app/src/main/java/com/tangem/tap/common/extensions/BackupService.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tangem.tap.common.extensions - -import com.tangem.domain.common.SaltPayWorkaround -import com.tangem.operations.backup.BackupService - -/** -[REDACTED_AUTHOR] - */ -@Suppress("MagicNumber") -fun BackupService.primaryCardIsSaltPayVisa(): Boolean { - return primaryCardId?.slice(0..3)?.let(SaltPayWorkaround::isVisaBatchId) ?: false -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/extensions/ImageRequest.kt b/app/src/main/java/com/tangem/tap/common/extensions/ImageRequest.kt index 9da1448d9c..2eb87310f9 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/ImageRequest.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/ImageRequest.kt @@ -1,32 +1,10 @@ package com.tangem.tap.common.extensions -import android.widget.ImageView -import coil.ImageLoader -import coil.imageLoader -import coil.load -import coil.request.Disposable import coil.request.ImageRequest -import com.tangem.tap.features.wallet.redux.Artwork -import com.tangem.wallet.R /** [REDACTED_AUTHOR] */ fun ImageRequest.Builder.cardImageData(any: Any?): ImageRequest.Builder = apply { - data(any?.parseData()) -} - -fun ImageView.loadCardImage( - data: Any?, - imageLoader: ImageLoader = context.imageLoader, - builder: ImageRequest.Builder.() -> Unit = {}, -): Disposable = this.load( - data = data?.parseData(), - imageLoader = imageLoader, - builder = builder, -) - -private fun Any?.parseData(): Any? = when { - this is String && this == Artwork.SALT_PAY_URL -> R.drawable.img_salt_pay_visa - else -> this + data(any) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt index 925cb0c728..36dfe253b5 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt @@ -2,9 +2,6 @@ package com.tangem.tap.common.extensions import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.BlockchainSdkError -import com.tangem.blockchain.common.Token -import com.tangem.blockchain.common.TransactionData -import com.tangem.blockchain.common.TransactionHistoryProvider import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.common.WalletManager import com.tangem.common.services.Result @@ -38,9 +35,6 @@ suspend fun WalletManager.safeUpdate(): Result = try { Result.Success(wallet) } else { update() - if (wallet.blockchain == Blockchain.SaltPay && this is TransactionHistoryProvider) { - this.getTransactionHistory(wallet.address, wallet.blockchain, wallet.getTokens()) - } Result.Success(wallet) } } catch (exception: Exception) { @@ -87,26 +81,10 @@ fun WalletManager?.getAddressData(): WalletDataModel.AddressData? { return if (addressDataList.isEmpty()) null else addressDataList[0] } -fun WalletManager.getBlockchainTxHistory(): List = wallet.getBlockchainTxHistory() - -fun WalletManager.getTokenTxHistory(token: Token): List = wallet.getTokenTxHistory(token) - fun WalletManager.Companion.stub(): T { val wallet = Wallet(Blockchain.Unknown, setOf(), Wallet.PublicKey(byteArrayOf(), null, null), setOf()) return object : WalletManager(wallet) { override val currentHost: String = "" override suspend fun update() {} } as T -} - -fun Wallet.getBlockchainTxHistory(): List { - return historyTransactions.filter { - it.contractAddress.isNullOrEmpty() - } -} - -fun Wallet.getTokenTxHistory(token: Token): List { - return historyTransactions.filter { - it.contractAddress == token.contractAddress - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt index de6bae2411..4ebc39d1d2 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt @@ -24,7 +24,6 @@ import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState import com.tangem.tap.features.onboarding.products.wallet.redux.BackupMiddleware import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletMiddleware import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState -import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayMiddleware import com.tangem.tap.features.saveWallet.redux.SaveWalletMiddleware import com.tangem.tap.features.saveWallet.redux.SaveWalletState import com.tangem.tap.features.send.redux.middlewares.SendMiddleware @@ -94,7 +93,6 @@ data class AppState( HomeMiddleware.handler, OnboardingNoteMiddleware.handler, OnboardingWalletMiddleware.handler, - OnboardingSaltPayMiddleware.handler, OnboardingOtherCardsMiddleware.handler, WalletMiddleware().walletMiddleware, TwinCardsMiddleware.handler, diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt index f589ca6743..d599f9c378 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt @@ -38,19 +38,16 @@ sealed class GlobalAction : Action { sealed class Onboarding : GlobalAction() { /** * Initiate an onboarding process. - * For resuming unfinished backup of standard Wallet and SaltPay cards see + * For resuming unfinished backup of standard Wallet see * BackupAction.CheckForUnfinishedBackup, GlobalAction.Onboarding.StartForUnfinishedBackup */ data class Start(val scanResponse: ScanResponse, val canSkipBackup: Boolean = true) : Onboarding() /** - * Initiate resuming of unfinished backup for standard Wallet and SaltPay cards. + * Initiate resuming of unfinished backup for standard Wallet. * See more BackupAction.CheckForUnfinishedBackup */ - data class StartForUnfinishedBackup( - val addedBackupCardsCount: Int, - val isSaltPayVisa: Boolean, - ) : Onboarding() + data class StartForUnfinishedBackup(val addedBackupCardsCount: Int) : Onboarding() object Stop : Onboarding() } diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt index 01d00c9a82..46835f3076 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt @@ -6,9 +6,7 @@ import com.tangem.common.extensions.guard import com.tangem.datasource.config.models.Config import com.tangem.domain.common.LogConfig import com.tangem.domain.common.extensions.withMainContext -import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.models.scan.CardDTO -import com.tangem.domain.models.scan.ProductType import com.tangem.domain.models.scan.ScanResponse import com.tangem.tap.common.entities.FiatCurrency import com.tangem.tap.common.extensions.dispatchDebugErrorNotification @@ -26,16 +24,12 @@ import com.tangem.tap.network.exchangeServices.ExchangeService import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoEnvironment import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoService import com.tangem.tap.network.exchangeServices.moonpay.MoonPayService -import com.tangem.tap.network.exchangeServices.utorg.UtorgAuthProvider -import com.tangem.tap.network.exchangeServices.utorg.UtorgEnvironment -import com.tangem.tap.network.exchangeServices.utorg.UtorgExchangeService import com.tangem.tap.preferencesStorage import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdkManager import com.tangem.tap.userTokensRepository import com.tangem.tap.walletCurrenciesManager -import com.tangem.wallet.BuildConfig import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.DispatchFunction @@ -109,13 +103,8 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di return } - val scanResponse = globalState.scanResponse ?: globalState.onboardingState.onboardingManager?.scanResponse - // if config not set -> try to get it based on a scanResponse.productType - val unsafeChatConfig = action.chatConfig ?: when { - scanResponse?.cardTypesResolver?.isSaltPay() == true -> config.saltPayConfig?.sprinklr - else -> config.zendesk - } + val unsafeChatConfig = action.chatConfig ?: config.zendesk val chatConfig = unsafeChatConfig.guard { store.dispatchDebugErrorNotification("ZendeskConfig not initialized") @@ -139,11 +128,10 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di store.state.globalState.scanResponse ?: store.state.globalState.onboardingState.onboardingManager?.scanResponse } - val productTypeProvider: () -> ProductType? = { scanResponseProvider.invoke()?.productType } val cardProvider: () -> CardDTO? = { scanResponseProvider.invoke()?.card } val exchangeManager = CurrencyExchangeManager( - buyService = makeBuyExchangeService(config, productTypeProvider), + buyService = makeBuyExchangeService(config), sellService = makeSellExchangeService(config), primaryRules = CardExchangeRules(cardProvider), ) @@ -213,28 +201,13 @@ private fun makeSellExchangeService(config: Config): ExchangeService { ) } -private fun makeBuyExchangeService(config: Config, productTypeProvider: () -> ProductType?): ExchangeService { +private fun makeBuyExchangeService(config: Config): ExchangeService { return BuyExchangeService( - productTypeProvider = productTypeProvider, mercuryoService = makeMercuryoExchangeService(config), - utorgService = makeUtorgExchangeService(config), ) } private fun makeMercuryoExchangeService(config: Config): MercuryoService { val mercuryoEnvironment = MercuryoEnvironment.prod(config.mercuryoWidgetId, config.mercuryoSecret) return MercuryoService(mercuryoEnvironment) -} - -private fun makeUtorgExchangeService(config: Config): UtorgExchangeService { - val saltPayConfig = requireNotNull(config.saltPayConfig) - - val utorgAuthProvider = UtorgAuthProvider(saltPayConfig.kycProvider.sidValue) - val utorgEnvironment = if (BuildConfig.DEBUG) { - UtorgEnvironment.stage(utorgAuthProvider, LogConfig.network.utorgService) - // UtorgEnvironment.mock() - } else { - UtorgEnvironment.prod(utorgAuthProvider) - } - return UtorgExchangeService(utorgEnvironment) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt index ffb1ece346..c395569c5c 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt @@ -229,7 +229,6 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co tangemSdk.config.cardIdDisplayFormat = when { scanResponse == null -> CardIdDisplayFormat.Full scanResponse.cardTypesResolver.isTangemTwins() -> CardIdDisplayFormat.LastLuhn(4) - scanResponse.cardTypesResolver.isSaltPay() -> CardIdDisplayFormat.None else -> CardIdDisplayFormat.Full } } diff --git a/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt b/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt index 19bbc1ae52..f963c6f982 100644 --- a/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt +++ b/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt @@ -4,7 +4,6 @@ import com.tangem.common.card.FirmwareVersion import com.tangem.common.extensions.toHexString import com.tangem.common.services.Result import com.tangem.domain.models.scan.CardDTO -import com.tangem.domain.common.TapWorkarounds.isSaltPay import com.tangem.domain.common.TwinCardNumber import com.tangem.domain.common.getTwinCardNumber import com.tangem.operations.attestation.CardVerifyAndGetInfo @@ -21,7 +20,7 @@ val CardDTO.isFirmwareMultiwalletAllowed: Boolean get() = firmwareVersion >= FirmwareVersion.MultiWalletAvailable && settings.maxWalletsCount > 1 val CardDTO.isHdWalletAllowedByApp: Boolean - get() = settings.isHDWalletAllowed && !isSaltPay + get() = settings.isHDWalletAllowed @Suppress("UnnecessaryParentheses") fun CardDTO.hasSignedHashes(): Boolean { diff --git a/app/src/main/java/com/tangem/tap/domain/model/WalletDataModel.kt b/app/src/main/java/com/tangem/tap/domain/model/WalletDataModel.kt index e6782972eb..fc0acca07c 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/WalletDataModel.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/WalletDataModel.kt @@ -1,6 +1,5 @@ package com.tangem.tap.domain.model -import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.address.AddressType import com.tangem.tap.domain.model.WalletDataModel.AddressData import com.tangem.tap.domain.model.WalletDataModel.Status @@ -28,7 +27,6 @@ data class WalletDataModel( val fiatRate: BigDecimal?, val isCardSingleToken: Boolean, val isCustom: Boolean, - val historyTransactions: List?, ) { data class WalletAddresses( diff --git a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt index 3cc1d2e5f5..d4e6cbd1fc 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt @@ -21,7 +21,6 @@ class UserWalletBuilder( get() = when (productType) { ProductType.Note -> "Note" ProductType.Twins -> "Twin" - ProductType.SaltPay -> "SaltPay" ProductType.Start2Coin -> "Start2Coin" ProductType.Wallet -> when { card.isBackupNotAllowed -> "Tangem card" diff --git a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt index 68626b34eb..64f5f8156d 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt @@ -60,7 +60,6 @@ class UserWalletIdBuilder private constructor( ProductType.Twins -> scanResponse.secondTwinPublicKey?.hexToBytes() ProductType.Note, ProductType.Wallet, - ProductType.SaltPay, ProductType.Start2Coin, -> null }, diff --git a/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt b/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt index ecca6f2314..e7d01ecdb6 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt @@ -9,8 +9,6 @@ import com.tangem.blockchain.common.WalletManager import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.domain.common.TapWorkarounds.derivationStyle import com.tangem.domain.common.util.cardTypesResolver -import com.tangem.tap.common.extensions.getBlockchainTxHistory -import com.tangem.tap.common.extensions.getTokenTxHistory import com.tangem.tap.domain.model.UserWallet import com.tangem.tap.domain.model.WalletDataModel import com.tangem.tap.domain.model.WalletStoreModel @@ -114,7 +112,6 @@ private fun BlockchainNetwork.getBlockchainWalletData( fiatRate = null, isCardSingleToken = false, isCustom = currency.isCustomCurrency(cardDerivationStyle), - historyTransactions = walletManager?.getBlockchainTxHistory(), ) } @@ -138,7 +135,6 @@ private fun BlockchainNetwork.getTokensWalletsData( fiatRate = null, isCardSingleToken = token == primaryToken, isCustom = currency.isCustomCurrency(cardDerivationStyle), - historyTransactions = walletManager?.getTokenTxHistory(token), ) } } @@ -156,7 +152,6 @@ private fun Blockchain.toBlockchainWalletData(walletManager: WalletManager): Wal fiatRate = null, isCardSingleToken = false, isCustom = false, - historyTransactions = walletManager.getBlockchainTxHistory(), ) } @@ -174,7 +169,6 @@ private fun Token.toTokenWalletData(walletManager: WalletManager, primaryToken: fiatRate = null, isCardSingleToken = this == primaryToken, isCustom = false, - historyTransactions = walletManager.getTokenTxHistory(this), ) } diff --git a/app/src/main/java/com/tangem/tap/domain/moduleMessage/ModuleMessageConverter.kt b/app/src/main/java/com/tangem/tap/domain/moduleMessage/ModuleMessageConverter.kt index 7c665e5cdd..efca92a6e8 100644 --- a/app/src/main/java/com/tangem/tap/domain/moduleMessage/ModuleMessageConverter.kt +++ b/app/src/main/java/com/tangem/tap/domain/moduleMessage/ModuleMessageConverter.kt @@ -5,8 +5,6 @@ import com.tangem.common.module.ModuleMessage import com.tangem.common.module.ModuleMessageConverter import com.tangem.domain.DomainModuleMessage import com.tangem.tap.domain.moduleMessage.domain.DomainMessageConverter -import com.tangem.tap.domain.moduleMessage.saltPay.SaltPayMessageConverter -import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayModuleMessage class ModuleMessageConverter( private val context: Context, @@ -15,7 +13,6 @@ class ModuleMessageConverter( override fun convert(message: ModuleMessage): ConvertedMessage { val convertedMessage = when (message) { is DomainModuleMessage -> DomainMessageConverter(context).convert(message) - is SaltPayModuleMessage -> SaltPayMessageConverter(context).convert(message) else -> null } return convertedMessage ?: convertUnknownMessage(message) diff --git a/app/src/main/java/com/tangem/tap/domain/moduleMessage/saltPay/SaltPayMessageConverter.kt b/app/src/main/java/com/tangem/tap/domain/moduleMessage/saltPay/SaltPayMessageConverter.kt deleted file mode 100644 index 9db1c78996..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/moduleMessage/saltPay/SaltPayMessageConverter.kt +++ /dev/null @@ -1,34 +0,0 @@ -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.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 - -/** -[REDACTED_AUTHOR] - */ -class SaltPayMessageConverter( - private val context: Context, -) : ModuleMessageConverter { - - override fun convert(message: SaltPayModuleMessage): ConvertedMessage? { - return when (message) { - is SaltPayModuleError -> SaltPayErrorConverter(context).convert(message) - else -> null - } - } -} - -class SaltPayErrorConverter( - private val context: Context, -) : ModuleMessageConverter { - - override fun convert(message: SaltPayModuleError): ConvertedMessage? = when (message) { - is SaltPayActivationError -> SaltPayActivationErrorConverter(context).convert(message) - else -> null - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/moduleMessage/saltPay/converter/SaltPayActivationErrorConverter.kt b/app/src/main/java/com/tangem/tap/domain/moduleMessage/saltPay/converter/SaltPayActivationErrorConverter.kt deleted file mode 100644 index 1771a2db47..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/moduleMessage/saltPay/converter/SaltPayActivationErrorConverter.kt +++ /dev/null @@ -1,53 +0,0 @@ -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.SaltPayActivationError -import com.tangem.wallet.R - -/** -[REDACTED_AUTHOR] - */ -internal class SaltPayActivationErrorConverter( - private val context: Context, -) : ModuleMessageConverter { - - override fun convert(message: SaltPayActivationError): ConvertedDialogMessage? { - val saltPayError = message as? SaltPayActivationError ?: throw UnsupportedOperationException() - - val dialogMessage = when (saltPayError) { - SaltPayActivationError.NoGas -> { - ConvertedDialogMessage( - title = context.getString(R.string.saltpay_error_no_gas_title), - message = context.getString(R.string.saltpay_error_no_gas_message), - ) - } - SaltPayActivationError.EmptyBackupCardScanned -> { - ConvertedDialogMessage( - title = context.getString(R.string.saltpay_error_empty_backup_title), - message = context.getString(R.string.saltpay_error_empty_backup_message), - ) - } - 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 == SaltPayActivationError.EMPTY_MESSAGE) { - saltPayError::class.java.simpleName - } else { - saltPayError.message - } - ConvertedDialogMessage( - title = context.getString(R.string.common_error), - message = errorMessage, - ) - } - } - - return dialogMessage - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt index e5a3579e07..f885b4fa13 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt @@ -5,20 +5,14 @@ import com.tangem.common.core.TangemError import com.tangem.common.core.TangemSdkError import com.tangem.common.doOnFailure import com.tangem.common.doOnSuccess -import com.tangem.common.services.Result import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.AnalyticsEvent import com.tangem.domain.common.extensions.withMainContext -import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.common.util.twinsIsTwinned import com.tangem.domain.models.scan.ScanResponse -import com.tangem.operations.backup.BackupService import com.tangem.tap.* import com.tangem.tap.common.analytics.paramsInterceptor.CardContextInterceptor -import com.tangem.tap.common.extensions.addContext -import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.common.extensions.primaryCardIsSaltPayVisa -import com.tangem.tap.common.extensions.setContext +import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction @@ -26,17 +20,11 @@ import com.tangem.tap.features.disclaimer.createDisclaimer import com.tangem.tap.features.disclaimer.redux.DisclaimerAction import com.tangem.tap.features.disclaimer.redux.DisclaimerCallback import com.tangem.tap.features.onboarding.OnboardingHelper -import com.tangem.tap.features.onboarding.OnboardingSaltPayHelper import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsStep -import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManagerFactory -import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayExceptionHandler -import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError -import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import org.rekotlin.Action internal object LegacyScanProcessor { @@ -85,24 +73,16 @@ internal object LegacyScanProcessor { onScanStateChange(false) sendAnalytics(analyticsEvent, scanResponse) - checkForUnfinishedBackupForSaltPay( - backupService = backupService, + showDisclaimerIfNeed( scanResponse = scanResponse, + disclaimerWillShow = disclaimerWillShow, onFailure = onFailure, - nextHandler = { scanResponse1 -> - showDisclaimerIfNeed( - scanResponse = scanResponse1, - disclaimerWillShow = disclaimerWillShow, - onFailure = onFailure, - nextHandler = { scanResponse2 -> - onScanSuccess( - scanResponse = scanResponse2, - onProgressStateChange = onProgressStateChange, - onSuccess = onSuccess, - onWalletNotCreated = onWalletNotCreated, - onFailure = onFailure, - ) - }, + nextHandler = { scanResponse2 -> + onScanSuccess( + scanResponse = scanResponse2, + onProgressStateChange = onProgressStateChange, + onSuccess = onSuccess, + onWalletNotCreated = onWalletNotCreated, ) }, ) @@ -121,35 +101,6 @@ internal object LegacyScanProcessor { } } - /** - * It checks only the SaltPay cards. To check for unfinished backups for the standard Wallet cards - * see BackupAction.CheckForUnfinishedBackup - * If user touches card other than Visa SaltPay - show dialog and block next processing - */ - private suspend inline fun checkForUnfinishedBackupForSaltPay( - backupService: BackupService, - scanResponse: ScanResponse, - nextHandler: (ScanResponse) -> Unit, - onFailure: suspend (error: TangemError) -> Unit, - ) { - if (!backupService.hasIncompletedBackup || !backupService.primaryCardIsSaltPayVisa()) { - nextHandler(scanResponse) - return - } - - val isTheSamePrimaryCard = backupService.primaryCardId - ?.let { it == scanResponse.card.cardId } - ?: false - - if (scanResponse.cardTypesResolver.isSaltPayWallet() || !isTheSamePrimaryCard) { - val error = SaltPayActivationError.PutVisaCard - SaltPayExceptionHandler.handle(error) - onFailure(TangemSdkError.ExceptionError(error)) - } else { - nextHandler(scanResponse) - } - } - private suspend inline fun showDisclaimerIfNeed( scanResponse: ScanResponse, crossinline disclaimerWillShow: () -> Unit = {}, @@ -165,7 +116,7 @@ internal object LegacyScanProcessor { scope.launch { delay(DELAY_SDK_DIALOG_CLOSE) disclaimerWillShow() - arrayOf( + store.dispatchWithMain( DisclaimerAction.Show( fromScreen = AppScreen.Home, callback = DisclaimerCallback( @@ -192,7 +143,6 @@ internal object LegacyScanProcessor { crossinline onProgressStateChange: suspend (showProgress: Boolean) -> Unit, crossinline onWalletNotCreated: suspend () -> Unit, crossinline onSuccess: suspend (ScanResponse) -> Unit, - crossinline onFailure: suspend (error: TangemError) -> Unit, ) { val globalState = store.state.globalState val tapWalletManager = globalState.tapWalletManager @@ -200,66 +150,21 @@ internal object LegacyScanProcessor { store.dispatchOnMain(TwinCardsAction.IfTwinsPrepareState(scanResponse)) - val cardTypesResolver = scanResponse.cardTypesResolver - if (cardTypesResolver.isSaltPay()) { - if (cardTypesResolver.isSaltPayVisa()) { - val manager = SaltPayActivationManagerFactory( - blockchain = scanResponse.cardTypesResolver.getBlockchain(), - card = scanResponse.card, - ).create() - val result = OnboardingSaltPayHelper.isOnboardingCase(scanResponse, manager) - delay(500) - withMainContext { - when (result) { - is Result.Success -> { - Analytics.addContext(scanResponse) - val isOnboardingCase = result.data - if (isOnboardingCase) { - onWalletNotCreated() - store.dispatch(GlobalAction.Onboarding.Start(scanResponse, canSkipBackup = false)) - store.dispatch(OnboardingSaltPayAction.SetDependencies(manager)) - store.dispatch(OnboardingSaltPayAction.Update(withAnalytics = false)) - navigateTo(AppScreen.OnboardingWallet) { onProgressStateChange(it) } - } else { - delay(DELAY_SDK_DIALOG_CLOSE) - onSuccess(scanResponse) - } - } - is Result.Failure -> { - delay(DELAY_SDK_DIALOG_CLOSE) - SaltPayExceptionHandler.handle(result.error) - onFailure(TangemSdkError.ExceptionError(result.error)) - } - } - } + if (OnboardingHelper.isOnboardingCase(scanResponse)) { + Analytics.addContext(scanResponse) + onWalletNotCreated() + store.dispatchOnMain(GlobalAction.Onboarding.Start(scanResponse, canSkipBackup = true)) + val appScreen = OnboardingHelper.whereToNavigate(scanResponse) + navigateTo(appScreen) { onProgressStateChange(it) } + } else { + Analytics.setContext(scanResponse) + if (scanResponse.twinsIsTwinned() && !preferencesStorage.wasTwinsOnboardingShown()) { + onWalletNotCreated() + store.dispatchOnMain(TwinCardsAction.SetStepOfScreen(TwinCardsStep.WelcomeOnly(scanResponse))) + navigateTo(AppScreen.OnboardingTwins) { onProgressStateChange(it) } } else { delay(DELAY_SDK_DIALOG_CLOSE) - if (scanResponse.card.backupStatus?.isActive == false) { - val error = SaltPayActivationError.PutVisaCard - SaltPayExceptionHandler.handle(error) - onFailure(TangemSdkError.ExceptionError(error)) - } else { - Analytics.setContext(scanResponse) - onSuccess(scanResponse) - } - } - } else { - if (OnboardingHelper.isOnboardingCase(scanResponse)) { - Analytics.addContext(scanResponse) - onWalletNotCreated() - store.dispatchOnMain(GlobalAction.Onboarding.Start(scanResponse, canSkipBackup = true)) - val appScreen = OnboardingHelper.whereToNavigate(scanResponse) - navigateTo(appScreen) { onProgressStateChange(it) } - } else { - Analytics.setContext(scanResponse) - if (scanResponse.twinsIsTwinned() && !preferencesStorage.wasTwinsOnboardingShown()) { - onWalletNotCreated() - store.dispatchOnMain(TwinCardsAction.SetStepOfScreen(TwinCardsStep.WelcomeOnly(scanResponse))) - navigateTo(AppScreen.OnboardingTwins) { onProgressStateChange(it) } - } else { - delay(DELAY_SDK_DIALOG_CLOSE) - onSuccess(scanResponse) - } + onSuccess(scanResponse) } } } diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt index 52d6cf4339..45a463343a 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt @@ -7,7 +7,6 @@ import com.tangem.core.analytics.AnalyticsEvent import com.tangem.domain.card.ScanCardException import com.tangem.domain.models.scan.ScanResponse import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE -import com.tangem.tap.backupService import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction @@ -52,7 +51,6 @@ internal object UseCaseScanProcessor { if (analyticsEvent != null) { add(AnalyticsChain(analyticsEvent)) } - add(CheckForUnfinishedSaltPayBackupChain(backupService)) add(DisclaimerChain(store, disclaimerWillShow)) add(CheckForOnboardingChain(store, store.state.globalState.tapWalletManager, preferencesStorage)) } @@ -91,9 +89,7 @@ internal object UseCaseScanProcessor { navigateTo(exception.onboardingRoute) onWalletNotCreated() } - is ScanChainException.PutSaltPayVisaCard, is ScanChainException.DisclaimerWasCanceled, - is ScanChainException.CheckForSaltPayOnboardingCaseException, -> onFailure(scanCardExceptionConverter.convertBack(exception)) } } diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/chains/CheckForOnboardingChain.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/chains/CheckForOnboardingChain.kt index 21d0e75290..ce46f2f527 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/chains/CheckForOnboardingChain.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/chains/CheckForOnboardingChain.kt @@ -3,12 +3,9 @@ package com.tangem.tap.domain.scanCard.chains import arrow.core.Either import arrow.core.left import arrow.core.right -import com.tangem.common.services.Result import com.tangem.core.analytics.Analytics import com.tangem.data.source.preferences.PreferencesDataSource import com.tangem.domain.card.ScanCardException -import com.tangem.domain.common.extensions.withMainContext -import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.common.util.twinsIsTwinned import com.tangem.domain.core.chain.Chain import com.tangem.domain.models.scan.ScanResponse @@ -21,13 +18,8 @@ import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.domain.TapWalletManager import com.tangem.tap.features.onboarding.OnboardingHelper -import com.tangem.tap.features.onboarding.OnboardingSaltPayHelper import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsStep -import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManagerFactory -import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayExceptionHandler -import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError -import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction import kotlinx.coroutines.delay import org.rekotlin.Store @@ -35,9 +27,7 @@ import org.rekotlin.Store * Handles the verification process to determine if the scanned card requires onboarding. * * Returns: - * - [ScanChainException.OnboardingNeeded] if onboarding required for none SaltPay cards. - * - [ScanChainException.CheckForSaltPayOnboardingCaseException] if unable to check for SaltPay onboarding case. - * - [ScanChainException.PutSaltPayVisaCard] if scanned SaltPay card is not activated and onboarding required. + * - [ScanChainException.OnboardingNeeded] if onboarding required. * * @param store the [Store] that holds the state of the app. * @param tapWalletManager manager responsible for handling operations related to the Wallet. @@ -54,54 +44,10 @@ class CheckForOnboardingChain( override suspend fun invoke( previousChainResult: ScanResponse, ): Either { - val cardTypesResolver = previousChainResult.cardTypesResolver - tapWalletManager.updateConfigManager(previousChainResult) store.dispatchOnMain(TwinCardsAction.IfTwinsPrepareState(previousChainResult)) return when { - cardTypesResolver.isSaltPayVisa() -> { - val manager = SaltPayActivationManagerFactory( - blockchain = previousChainResult.cardTypesResolver.getBlockchain(), - card = previousChainResult.card, - ).create() - val result = OnboardingSaltPayHelper.isOnboardingCase(previousChainResult, manager) - delay(timeMillis = 500) - withMainContext { - when (result) { - is Result.Success -> { - Analytics.addContext(previousChainResult) - val isOnboardingCase = result.data - if (isOnboardingCase) { - store.dispatch( - GlobalAction.Onboarding.Start(previousChainResult, canSkipBackup = false), - ) - store.dispatch(OnboardingSaltPayAction.SetDependencies(manager)) - store.dispatch(OnboardingSaltPayAction.Update(withAnalytics = false)) - ScanChainException.OnboardingNeeded(AppScreen.OnboardingWallet).left() - } else { - delay(DELAY_SDK_DIALOG_CLOSE) - previousChainResult.right() - } - } - is Result.Failure -> { - delay(DELAY_SDK_DIALOG_CLOSE) - SaltPayExceptionHandler.handle(result.error) - ScanChainException.CheckForSaltPayOnboardingCaseException(result.error).left() - } - } - } - } - cardTypesResolver.isSaltPayWallet() -> { - delay(DELAY_SDK_DIALOG_CLOSE) - if (previousChainResult.card.backupStatus?.isActive == false) { - SaltPayExceptionHandler.handle(SaltPayActivationError.PutVisaCard) - ScanChainException.PutSaltPayVisaCard.left() - } else { - Analytics.setContext(previousChainResult) - previousChainResult.right() - } - } OnboardingHelper.isOnboardingCase(previousChainResult) -> { Analytics.addContext(previousChainResult) store.dispatchOnMain(GlobalAction.Onboarding.Start(previousChainResult, canSkipBackup = true)) diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/chains/CheckForUnfinishedSaltPayBackupChain.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/chains/CheckForUnfinishedSaltPayBackupChain.kt deleted file mode 100644 index f01f9f76d7..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/chains/CheckForUnfinishedSaltPayBackupChain.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.tangem.tap.domain.scanCard.chains - -import arrow.core.Either -import arrow.core.left -import arrow.core.right -import com.tangem.domain.card.ScanCardException -import com.tangem.domain.common.util.cardTypesResolver -import com.tangem.domain.core.chain.Chain -import com.tangem.domain.models.scan.ScanResponse -import com.tangem.operations.backup.BackupService -import com.tangem.tap.common.extensions.primaryCardIsSaltPayVisa - -/** - * Handles the verification for unfinished SaltPay backup processes after the card scanning operation. - * - * Returns [ScanChainException.PutSaltPayVisaCard] if backup is not finished. - * - * @param backupService a service responsible for managing backup operations, used here to check for unfinished backups - * and verify the primary card type. - * - * @see Chain for more information about the Chain interface. - */ -internal class CheckForUnfinishedSaltPayBackupChain( - private val backupService: BackupService, -) : Chain { - - override suspend fun invoke( - previousChainResult: ScanResponse, - ): Either { - if (!backupService.hasIncompletedBackup || !backupService.primaryCardIsSaltPayVisa()) { - return previousChainResult.right() - } - - val isTheSamePrimaryCard = backupService.primaryCardId - ?.let { it == previousChainResult.card.cardId } - ?: false - - return if (previousChainResult.cardTypesResolver.isSaltPayWallet() || !isTheSamePrimaryCard) { - ScanChainException.PutSaltPayVisaCard.left() - } else { - previousChainResult.right() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/chains/ScanChainException.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/chains/ScanChainException.kt index 626465c7ee..6709cb8966 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/chains/ScanChainException.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/chains/ScanChainException.kt @@ -5,11 +5,6 @@ import com.tangem.tap.common.redux.navigation.AppScreen sealed class ScanChainException : ScanCardException.ChainException() { - /** - * May be returned from [CheckForOnboardingChain] and [CheckForUnfinishedSaltPayBackupChain] - * */ - object PutSaltPayVisaCard : ScanChainException() - /** * May be returned from [DisclaimerChain] * */ @@ -21,11 +16,4 @@ sealed class ScanChainException : ScanCardException.ChainException() { * @param onboardingRoute route where to navigate * */ data class OnboardingNeeded(val onboardingRoute: AppScreen) : ScanChainException() - - /** - * May be returned from [CheckForOnboardingChain] - * - * @param cause cause of exception - * */ - data class CheckForSaltPayOnboardingCaseException(override val cause: Throwable?) : ScanChainException() } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/utils/ScanCardExceptionConverter.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/utils/ScanCardExceptionConverter.kt index f04df13017..53062e6918 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/utils/ScanCardExceptionConverter.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/utils/ScanCardExceptionConverter.kt @@ -4,7 +4,6 @@ import com.tangem.common.core.TangemError import com.tangem.common.core.TangemSdkError import com.tangem.domain.card.ScanCardException import com.tangem.tap.domain.scanCard.chains.ScanChainException -import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError import com.tangem.utils.converter.TwoWayConverter internal class ScanCardExceptionConverter : TwoWayConverter { @@ -35,10 +34,6 @@ internal class ScanCardExceptionConverter : TwoWayConverter TangemSdkError.UserCancelled() - is ScanChainException.PutSaltPayVisaCard -> TangemSdkError.ExceptionError( - SaltPayActivationError.PutVisaCard, - ) - is ScanChainException.CheckForSaltPayOnboardingCaseException, is ScanChainException.OnboardingNeeded, null, -> TangemSdkError.ExceptionError(e?.cause) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt index 821e82be32..69a78dfb46 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt @@ -20,7 +20,6 @@ import com.tangem.crypto.CryptoUtils import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.domain.common.TapWorkarounds.isExcluded import com.tangem.domain.common.TapWorkarounds.isNotSupportedInThatRelease -import com.tangem.domain.common.TapWorkarounds.isSaltPay import com.tangem.domain.common.TapWorkarounds.isStart2Coin import com.tangem.domain.common.TapWorkarounds.isTangemTwins import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation @@ -189,9 +188,7 @@ private class ScanWalletProcessor( val activationInProgress = preferencesStorage.usedCardsPrefStorage.isActivationInProgress(card.cardId) @Suppress("ComplexCondition") - if (card.backupStatus == CardDTO.BackupStatus.NoBackup && card.wallets.isNotEmpty() && - (activationInProgress || card.isSaltPay) - ) { + if (card.backupStatus == CardDTO.BackupStatus.NoBackup && card.wallets.isNotEmpty() && activationInProgress) { StartPrimaryCardLinkingTask().run(session) { linkingResult -> when (linkingResult) { is CompletionResult.Success -> { @@ -213,10 +210,7 @@ private class ScanWalletProcessor( session: CardSession, callback: (result: CompletionResult) -> Unit, ) { - val productType = when (card.isSaltPay) { - true -> ProductType.SaltPay - else -> ProductType.Wallet - } + val productType = ProductType.Wallet scope.launch { val derivations = collectDerivations(card) if (derivations.isEmpty() || !card.settings.isHDWalletAllowed) { diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/GetCardImageUseCase.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/GetCardImageUseCase.kt index 71415134a2..9d218c840f 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/GetCardImageUseCase.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/GetCardImageUseCase.kt @@ -2,7 +2,6 @@ package com.tangem.tap.domain.userWalletList import com.tangem.common.extensions.toHexString import com.tangem.common.services.Result -import com.tangem.domain.common.SaltPayWorkaround import com.tangem.domain.common.TwinCardNumber import com.tangem.domain.common.TwinsHelper import com.tangem.operations.attestation.OnlineCardVerifier @@ -43,7 +42,6 @@ class GetCardImageUseCase(private val verifier: OnlineCardVerifier = OnlineCardV return when { cardId.startsWith(Artwork.SERGIO_CARD_ID) -> Artwork.SERGIO_CARD_URL cardId.startsWith(Artwork.MARTA_CARD_ID) -> Artwork.MARTA_CARD_URL - SaltPayWorkaround.isSaltPayCardId(cardId) -> Artwork.SALT_PAY_URL else -> when (TwinsHelper.getTwinCardNumber(cardId)) { TwinCardNumber.First -> Artwork.TWIN_CARD_1 TwinCardNumber.Second -> Artwork.TWIN_CARD_2 diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt index 6b2aa5ccff..e276bd51db 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt @@ -2,9 +2,7 @@ package com.tangem.tap.domain.walletStores.repository.implementation import com.tangem.blockchain.blockchains.solana.RentProvider import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.BlockchainSdkError -import com.tangem.blockchain.common.TransactionHistoryProvider import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.extensions.Result.Failure @@ -35,7 +33,6 @@ import com.tangem.tap.domain.walletStores.repository.implementation.utils.update import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithFiatRates import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithMissedDerivation import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithRent -import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithTxHistories import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithUnreachable import com.tangem.tap.domain.walletStores.storage.WalletManagerStorage import com.tangem.tap.domain.walletStores.storage.WalletStoresStorage @@ -248,11 +245,6 @@ internal class DefaultWalletAmountsRepository( TestActions.testAmountInjectionForWalletManagerEnabled = false } else { walletManager.update() - - val wallet = walletManager.wallet - if (wallet.blockchain == Blockchain.SaltPay && walletManager is TransactionHistoryProvider) { - walletManager.getTransactionHistory(wallet.address, wallet.blockchain, wallet.getTokens()) - } } } @@ -349,7 +341,7 @@ internal class DefaultWalletAmountsRepository( it.updateWithDemoAmounts(wallet = updatedWallet) } else { it.updateWithAmounts(wallet = updatedWallet) - }.updateWithTxHistories(wallet = updatedWallet) + } }, ) } diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt index 396329ad4f..85fd9d5c8e 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt @@ -5,8 +5,6 @@ import com.tangem.blockchain.common.BlockchainSdkError import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.common.address.AddressType import com.tangem.common.core.TangemError -import com.tangem.tap.common.extensions.getBlockchainTxHistory -import com.tangem.tap.common.extensions.getTokenTxHistory import com.tangem.tap.domain.extensions.amountToCreateAccount import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.model.WalletDataModel @@ -28,21 +26,6 @@ internal fun List.updateWithFiatRates(fiatRates: Map wallet.getBlockchainTxHistory() - is Currency.Token -> wallet.getTokenTxHistory(currency.token) - }, - ) -} - -internal fun List.updateWithTxHistories(wallet: Wallet): List { - return this.map { walletData -> - walletData.updateWithTxHistory(wallet) - } -} - internal fun List.updateWithAmounts(wallet: Wallet): List { return this.map { walletData -> walletData.updateWithAmount(wallet) diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt index 627c5f93d3..069f77fe4b 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt @@ -40,12 +40,6 @@ internal fun WalletStoreModel.updateWithError(wallet: Wallet, error: TangemError ) } -internal fun WalletStoreModel.updateWithTxHistories(wallet: Wallet): WalletStoreModel { - return this.copy( - walletsData = walletsData.updateWithTxHistories(wallet = wallet), - ) -} - internal fun WalletStoreModel.updateWithAmounts(wallet: Wallet): WalletStoreModel { return this.copy( walletsData = walletsData.updateWithAmounts(wallet = wallet), diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt index 85e80df897..e28b9cd398 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt @@ -98,7 +98,7 @@ private fun prepareSecurityOptions(card: CardDTO, cardTypesResolver: CardTypesRe } } val allowedSecurityOptions = when { - cardTypesResolver.isStart2Coin() || cardTypesResolver.isTangemNote() || cardTypesResolver.isSaltPay() -> { + cardTypesResolver.isStart2Coin() || cardTypesResolver.isTangemNote() -> { EnumSet.of(SecurityOption.LongTap) } card.settings.isBackupAllowed -> { @@ -116,7 +116,7 @@ private fun prepareSecurityOptions(card: CardDTO, cardTypesResolver: CardTypesRe private fun isResetToFactoryAllowedByCard(card: CardDTO, cardTypesResolver: CardTypesResolver): Boolean { val hasPermanentWallet = card.wallets.any { it.settings.isPermanent } - val isNotAllowed = hasPermanentWallet || cardTypesResolver.isSaltPay() || cardTypesResolver.isStart2Coin() + val isNotAllowed = hasPermanentWallet || cardTypesResolver.isStart2Coin() return !isNotAllowed } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt index 10edfda464..e9766c6147 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt @@ -32,13 +32,8 @@ class DetailsViewModel(private val store: Store) { SettingsElement.WalletConnect -> { if (cardTypesResolver?.isMultiwalletAllowed() == true) it else null } - SettingsElement.SendFeedback -> - if (cardTypesResolver?.isSaltPay() != true) it else null - SettingsElement.LinkMoreCards -> { - // if (state.createBackupAllowed) it else null - // TODO: SaltPay: temporary excluding backup process for Visa cards - if (state.createBackupAllowed && cardTypesResolver?.isSaltPay() != true) it else null - } + SettingsElement.SendFeedback -> it + SettingsElement.LinkMoreCards -> if (state.createBackupAllowed) it else null SettingsElement.PrivacyPolicy -> { if (state.privacyPolicyUrl != null) it else null } diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/Disclaimer.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/Disclaimer.kt index 27dd88ee13..6f09751342 100644 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/Disclaimer.kt +++ b/app/src/main/java/com/tangem/tap/features/disclaimer/Disclaimer.kt @@ -40,12 +40,6 @@ class TangemDisclaimer(dataProvider: DisclaimerDataProvider) : BaseDisclaimer(da override fun getPreferenceKey(): String = "tangem_tos_accepted" } -class SaltPayDisclaimer(dataProvider: DisclaimerDataProvider) : BaseDisclaimer(dataProvider) { - override fun type(): DisclaimerType = DisclaimerType.SaltPay - override fun getUri(): Uri = Uri.parse("$baseUrl/soltpay_tos.html") - override fun getPreferenceKey(): String = "saltPay_tos_accepted" -} - class Start2CoinDisclaimer(dataProvider: DisclaimerDataProvider) : BaseDisclaimer(dataProvider) { override fun type(): DisclaimerType = DisclaimerType.Start2Coin override fun getUri(): Uri = Uri.parse("$baseUrl/" + filename(dataProvider.getLanguage(), getRegion())) diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/DisclaimerType.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/DisclaimerType.kt index 56519de4ff..b01b2b6f60 100644 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/DisclaimerType.kt +++ b/app/src/main/java/com/tangem/tap/features/disclaimer/DisclaimerType.kt @@ -1,6 +1,5 @@ package com.tangem.tap.features.disclaimer -import com.tangem.domain.common.TapWorkarounds.isSaltPay import com.tangem.domain.common.TapWorkarounds.isStart2Coin import com.tangem.domain.models.scan.CardDTO import com.tangem.data.source.preferences.storage.DisclaimerPrefStorage @@ -12,14 +11,12 @@ import java.util.Locale */ enum class DisclaimerType { Tangem, - SaltPay, Start2Coin, ; companion object { fun get(cardDTO: CardDTO): DisclaimerType { return when { - cardDTO.isSaltPay -> SaltPay cardDTO.isStart2Coin -> Start2Coin else -> Tangem } @@ -31,7 +28,6 @@ fun DisclaimerType.createDisclaimer(cardDTO: CardDTO): Disclaimer { val dataProvider = provideDisclaimerDataProvider(cardDTO.cardId) return when (this) { DisclaimerType.Tangem -> TangemDisclaimer(dataProvider) - DisclaimerType.SaltPay -> SaltPayDisclaimer(dataProvider) DisclaimerType.Start2Coin -> Start2CoinDisclaimer(dataProvider) } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt index b9e5db5876..6079110e39 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt @@ -62,7 +62,6 @@ object OnboardingHelper { AppScreen.OnboardingOther } ProductType.Twins -> AppScreen.OnboardingTwins - ProductType.SaltPay -> AppScreen.OnboardingWallet ProductType.Start2Coin -> throw java.lang.UnsupportedOperationException( "Onboarding for Start2Coin cards is not supported", ) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingSaltPayHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingSaltPayHelper.kt deleted file mode 100644 index ab267f9dda..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingSaltPayHelper.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.tangem.tap.features.onboarding - -import com.tangem.common.services.Result -import com.tangem.domain.models.scan.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.SaltPayActivationError -import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayActivationStep -import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.update -import com.tangem.tap.preferencesStorage - -/** -[REDACTED_AUTHOR] - */ -object OnboardingSaltPayHelper { - - suspend fun isOnboardingCase(scanResponse: ScanResponse, manager: SaltPayActivationManager): Result { - return try { - val updatedStep = manager.update(SaltPayActivationStep.None, null).successOr { return it } - - val cardStorage = preferencesStorage.usedCardsPrefStorage - val activationIsFinished = cardStorage.isActivationFinished(scanResponse.card.cardId) - if (updatedStep == SaltPayActivationStep.Success && !activationIsFinished) { - cardStorage.activationFinished(scanResponse.card.cardId) - } - val isActivationCase = updatedStep != SaltPayActivationStep.Success - val isBackupCase = scanResponse.card.backupStatus?.isActive == false - Result.Success(isActivationCase || isBackupCase) - } catch (ex: Exception) { - Result.Failure(ex) - } catch (error: SaltPayActivationError) { - Result.Failure(error) - } - } - - @Suppress("UnusedPrivateMember") - fun testProceedToOnboarding(scanResponse: ScanResponse, manager: SaltPayActivationManager): Result = - Result.Success(true) - - @Suppress("UnusedPrivateMember") - fun testProceedToMainScreen(scanResponse: ScanResponse, manager: SaltPayActivationManager): Result = - Result.Success(false) -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt index 227cdb626d..c021c9fad5 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt @@ -10,8 +10,6 @@ import org.rekotlin.Action sealed class OnboardingWalletAction : Action { object Init : OnboardingWalletAction() object GetToCreateWalletStep : OnboardingWalletAction() - object GetToSaltPayStep : OnboardingWalletAction() - object CreateWallet : OnboardingWalletAction() data class WalletWasCreated( val result: CompletionResult, @@ -57,7 +55,7 @@ sealed class BackupAction : Action { object ScanPrimaryCard : BackupAction() /** - * Check for unfinished backup of standard Wallets and SaltPay cards + * Check for unfinished backup of standard Wallets * See more GlobalAction.Onboarding.StartForUnfinishedBackup */ object CheckForUnfinishedBackup : BackupAction() @@ -82,9 +80,6 @@ sealed class BackupAction : Action { data class PrepareToWriteBackupCard(val cardNumber: Int) : BackupAction() data class WriteBackupCard(val cardNumber: Int) : BackupAction() - /** - * It always calls for the SaltPay cards when resuming the activation process. - */ data class FinishBackup(val withAnalytics: Boolean = true) : BackupAction() object DiscardBackup : BackupAction() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index ce33520089..2f4be5416d 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -6,7 +6,6 @@ import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.ifNotNull import com.tangem.core.analytics.Analytics -import com.tangem.domain.common.TapWorkarounds.isSaltPay import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.models.scan.CardDTO @@ -19,7 +18,6 @@ import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.common.extensions.primaryCardIsSaltPayVisa import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen @@ -30,8 +28,6 @@ import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.onboarding.OnboardingDialog import com.tangem.tap.features.onboarding.OnboardingHelper -import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManagerFactory -import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction import com.tangem.tap.features.wallet.models.toCurrencies import com.tangem.tap.features.wallet.redux.Artwork import kotlinx.coroutines.launch @@ -70,7 +66,7 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch: when (action) { OnboardingWalletAction.Init -> { ifNotNull(onboardingManager, card) { manager, card -> - if (!card.isSaltPay && !manager.isActivationStarted(card.cardId)) { + if (!manager.isActivationStarted(card.cardId)) { Analytics.send(Onboarding.Started()) } } @@ -83,20 +79,7 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch: store.dispatch(OnboardingWalletAction.ResumeBackup) } card.wallets.isNotEmpty() && card.backupStatus?.isActive == true -> { - when { - // check for unfinished backup for saltPay cards. See more - scanResponse.cardTypesResolver.isSaltPay() && backupService.hasIncompletedBackup -> { - store.dispatch(OnboardingWalletAction.ResumeBackup) - } - - scanResponse.cardTypesResolver.isSaltPay() -> { - store.dispatch(OnboardingWalletAction.GetToSaltPayStep) - store.dispatch(BackupAction.FinishBackup(withAnalytics = false)) - store.dispatch(OnboardingSaltPayAction.OnSwitchedToSaltPayProcess) - } - - else -> store.dispatch(BackupAction.FinishBackup()) - } + store.dispatch(BackupAction.FinishBackup()) } else -> { store.dispatch(OnboardingWalletAction.GetToCreateWalletStep) @@ -180,12 +163,8 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch: if (onboardingWalletState.backupState.backupStep == BackupStep.InitBackup || onboardingWalletState.backupState.backupStep == BackupStep.Finished ) { - if (onboardingWalletState.isSaltPay) { - BackupAction.StartBackup - } else { - Analytics.send(Onboarding.Backup.ScreenOpened()) - BackupAction.IntroduceBackup - } + Analytics.send(Onboarding.Backup.ScreenOpened()) + BackupAction.IntroduceBackup } else { null } @@ -348,11 +327,6 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) } } is BackupAction.AddBackupCard -> { - onboardingWalletState.backupCardIdFilter?.let { - backupService.skipCompatibilityChecks = true - tangemSdk.config.filter.cardIdFilter = it - } - backupService.addBackupCard { result -> backupService.skipCompatibilityChecks = false tangemSdk.config.filter.cardIdFilter = null @@ -400,7 +374,6 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) if (action.accessCodeConfirmation == backupState.accessCode) { store.dispatch(BackupAction.SetAccessCodeError(null)) backupService.setAccessCode(action.accessCodeConfirmation) - store.dispatch(OnboardingSaltPayAction.SetAccessCode(action.accessCodeConfirmation)) store.dispatch(BackupAction.PrepareToWritePrimaryCard) } else { store.dispatch(BackupAction.SetAccessCodeError(AccessCodeError.CodesDoNotMatch)) @@ -421,7 +394,6 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) when (result) { is CompletionResult.Success -> { if (backupService.currentState == BackupService.State.Finished) { - initSaltPayOnBackupFinishedIfNeeded(scanResponse, onboardingWalletState) store.dispatchOnMain(BackupAction.FinishBackup()) } else { store.dispatchOnMain(BackupAction.PrepareToWriteBackupCard(action.cardNumber + 1)) @@ -450,14 +422,12 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) store.dispatch( GlobalAction.Onboarding.StartForUnfinishedBackup( addedBackupCardsCount = backupService.addedBackupCardsCount, - isSaltPayVisa = backupService.primaryCardIsSaltPayVisa(), ), ) store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet)) } is BackupAction.SkipBackup -> { Analytics.send(Onboarding.Backup.Skipped()) - if (onboardingWalletState.isSaltPay) return Analytics.send(Onboarding.Finished()) finishCardActivation(gatherCardIds(backupState, card)) @@ -466,7 +436,6 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) if (action.withAnalytics) { Analytics.send(Onboarding.Backup.Finished(backupState.backupCardsNumber)) } - if (onboardingWalletState.isSaltPay) return val notActivatedCardIds = gatherCardIds(backupState, card) .mapNotNull { if (cardActivationIsFinished(it)) null else it } @@ -492,7 +461,6 @@ private fun cardActivationIsFinished(cardId: String): Boolean { /** * Standard Wallet cards start activation at OnboardingWalletAction.CreateWallet - * SaltPay cards start activation at OnboardingWalletAction.StartSaltPayCardActivation */ private fun startCardActivation(scanResponse: ScanResponse) { preferencesStorage.usedCardsPrefStorage.activationStarted(scanResponse.card.cardId) @@ -500,7 +468,6 @@ private fun startCardActivation(scanResponse: ScanResponse) { /** * Standard Wallet cards finish activation at BackupAction.SkipBackup and BackupAction.FinishBackup - * SaltPay cards finish activation at OnboardingWalletAction.FinishOnboarding */ internal fun finishCardActivation(cardIds: List) { cardIds.forEach { cardId -> @@ -514,31 +481,10 @@ internal fun gatherCardIds(backupState: BackupState, card: CardDTO?): List { - if (state.isSaltPay) { - showInterruptOnboardingDialog() - } else { - OnboardingHelper.onInterrupted() - store.dispatch(NavigationAction.PopBackTo()) - } + OnboardingHelper.onInterrupted() + store.dispatch(NavigationAction.PopBackTo()) } } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt index 30b94a73c6..077e4b82aa 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt @@ -1,11 +1,8 @@ package com.tangem.tap.features.onboarding.products.wallet.redux -import com.tangem.domain.common.util.cardTypesResolver import com.tangem.tap.backupService import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction -import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayReducer import org.rekotlin.Action object OnboardingWalletReducer { @@ -17,15 +14,11 @@ private fun internalReduce(action: Action, appState: AppState): OnboardingWallet return when (action) { is GlobalAction.Onboarding -> ReducerForGlobalAction.reduce(action, state) - is OnboardingSaltPayAction -> OnboardingSaltPayReducer.reduce(action, state) - is BackupAction -> state.copy(backupState = BackupReducer.reduce(action, state.backupState, state.isSaltPay)) + is BackupAction -> state.copy(backupState = BackupReducer.reduce(action, state.backupState)) is OnboardingWallet2Action -> OnboardingWallet2Reducer.reduce(action, state) is OnboardingWalletAction.GetToCreateWalletStep -> state.copy( step = OnboardingWalletStep.CreateWallet, ) - is OnboardingWalletAction.GetToSaltPayStep -> state.copy( - step = OnboardingWalletStep.SaltPay, - ) is OnboardingWalletAction.ResumeBackup -> state.copy(step = OnboardingWalletStep.Backup) is OnboardingWalletAction.SetArtworkUrl -> { state.copy(cardArtworkUri = action.artworkUri) @@ -36,16 +29,17 @@ private fun internalReduce(action: Action, appState: AppState): OnboardingWallet } private object ReducerForGlobalAction { + + private const val MAX_BACKUP_CARDS = 2 + fun reduce(action: GlobalAction.Onboarding, state: OnboardingWalletState): OnboardingWalletState { return when (action) { is GlobalAction.Onboarding.Start -> { - val isSaltPay = action.scanResponse.cardTypesResolver.isSaltPay() OnboardingWalletState( backupState = state.backupState.copy( - maxBackupCards = maxBackupCards(isSaltPay), - canSkipBackup = if (isSaltPay) false else action.canSkipBackup, + maxBackupCards = MAX_BACKUP_CARDS, + canSkipBackup = action.canSkipBackup, ), - isSaltPay = isSaltPay, ) } is GlobalAction.Onboarding.StartForUnfinishedBackup -> { @@ -55,14 +49,11 @@ private object ReducerForGlobalAction { canSkipBackup = false, isInterruptedBackup = true, ), - isSaltPay = action.isSaltPayVisa, ) } else -> state } } - - private fun maxBackupCards(isSaltPay: Boolean): Int = if (isSaltPay) 1 else 2 } private object OnboardingWallet2Reducer { @@ -78,11 +69,11 @@ private object OnboardingWallet2Reducer { private object BackupReducer { @Suppress("ComplexMethod") - fun reduce(action: BackupAction, state: BackupState, isSaltPay: Boolean): BackupState { + fun reduce(action: BackupAction, state: BackupState): BackupState { return when (action) { is BackupAction.IntroduceBackup -> BackupState( backupStep = BackupStep.InitBackup, - maxBackupCards = if (isSaltPay) 1 else 2, + maxBackupCards = 2, canSkipBackup = state.canSkipBackup, ) BackupAction.StartAddingPrimaryCard -> state.copy(backupStep = BackupStep.ScanOriginCard) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt index 94ce0d1f54..cc59a4fb61 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt @@ -2,11 +2,7 @@ package com.tangem.tap.features.onboarding.products.wallet.redux import android.graphics.Bitmap import android.net.Uri -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.SaltPayActivationStep import org.rekotlin.StateType /** @@ -16,32 +12,21 @@ data class OnboardingWalletState( val step: OnboardingWalletStep = OnboardingWalletStep.None, val wallet2State: OnboardingWallet2State? = null, val backupState: BackupState = BackupState(), - val onboardingSaltPayState: OnboardingSaltPayState? = null, - val isSaltPay: Boolean = false, val cardArtworkUri: Uri? = null, val showConfetti: Boolean = false, ) : StateType { - val backupCardIdFilter: CardFilter.Companion.CardIdFilter? - get() = when { - isSaltPay -> CardFilter.Companion.CardIdFilter.Allow( - items = SaltPayWorkaround.walletCardIds.toSet(), - ranges = SaltPayWorkaround.walletCardIdRanges, - ) - else -> null - } - @Suppress("MagicNumber") fun getMaxProgress(): Int { - val baseProgress = if (isSaltPay) 12 else 6 + val baseProgress = 6 return getWallet2Progress() + baseProgress } @Suppress("ComplexMethod", "MagicNumber") fun getProgressStep(): Int { - val progressByStep = when { - step == OnboardingWalletStep.CreateWallet -> 1 - step == OnboardingWalletStep.Backup -> { + val progressByStep = when (step) { + OnboardingWalletStep.CreateWallet -> 1 + OnboardingWalletStep.Backup -> { when (backupState.backupStep) { BackupStep.InitBackup -> 2 BackupStep.ScanOriginCard -> 3 @@ -53,21 +38,7 @@ data class OnboardingWalletState( BackupStep.Finished -> getMaxProgress() } } - step == OnboardingWalletStep.SaltPay && isSaltPay -> { - when (onboardingSaltPayState!!.step) { - SaltPayActivationStep.None, SaltPayActivationStep.NoGas -> 0 - SaltPayActivationStep.NeedPin -> 7 - SaltPayActivationStep.CardRegistration -> 8 - SaltPayActivationStep.KycIntro, SaltPayActivationStep.KycStart, - SaltPayActivationStep.KycWaiting, SaltPayActivationStep.KycReject, - -> 9 - SaltPayActivationStep.Claim -> 10 - SaltPayActivationStep.ClaimInProgress -> 11 - SaltPayActivationStep.ClaimSuccess, SaltPayActivationStep.Success, - -> getMaxProgress() - } - } - step == OnboardingWalletStep.Done -> getMaxProgress() + OnboardingWalletStep.Done -> getMaxProgress() else -> 1 } @@ -82,7 +53,7 @@ data class OnboardingWallet2State( ) enum class OnboardingWalletStep { - None, CreateWallet, SaltPay, Backup, Done + None, CreateWallet, Backup, Done } data class BackupState( diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/GnosisRegistrator.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/GnosisRegistrator.kt deleted file mode 100644 index b5dfe53817..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/GnosisRegistrator.kt +++ /dev/null @@ -1,230 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay - -import com.tangem.blockchain.blockchains.ethereum.CompiledEthereumTransaction -import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager -import com.tangem.blockchain.blockchains.ethereum.SignedEthereumTransaction -import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.BlockchainSdkError -import com.tangem.blockchain.common.TransactionSigner -import com.tangem.blockchain.common.WalletManager -import com.tangem.blockchain.extensions.Result -import com.tangem.blockchain.extensions.SimpleResult -import com.tangem.blockchain.extensions.successOr -import com.tangem.common.extensions.guard -import com.tangem.domain.common.extensions.successOr -import com.tangem.tap.common.extensions.isPositive -import com.tangem.tap.common.extensions.safeUpdate -import com.tangem.tap.common.extensions.stub -import com.tangem.tap.domain.getFirstToken -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope -import java.math.BigDecimal -import java.math.BigInteger -import java.math.MathContext -import java.math.RoundingMode -import java.util.concurrent.atomic.AtomicLong - -/** -[REDACTED_AUTHOR] - */ -class GnosisRegistrator( - val walletManager: EthereumWalletManager, -) { - - private val walletAddress = walletManager.wallet.address - private val blockchain = walletManager.wallet.blockchain - private val token = walletManager.wallet.getFirstToken().guard { - throw NullPointerException("WalletManager for GnosisRegistrator must contain token") - } - - private val otpProcessorContractAddress: String = when (blockchain) { - Blockchain.SaltPay -> "0xc659f4FEd7A84a188F54cBA4A7a49D77c1a20522" - else -> throw IllegalArgumentException("GnosisRegistrator supports only the SaltPay blockchain") - } - - private val addressTreasureSafe = "0x24A3c2382497075b6D93258f5938f7B661c06318" - - private val atomicNonce = AtomicLong() - - suspend fun checkHasGas(): Result { - // return Result.Success(true) // test - val wallet = walletManager.safeUpdate().successOr { - return Result.Failure(BlockchainSdkError.WrappedThrowable(it.error)) - } - - val hasGas = wallet.amounts[AmountType.Coin]?.value?.isPositive() ?: false - return Result.Success(hasGas) - } - - suspend fun prepareBeforeMakingTxs(): Result { - walletManager.safeUpdate().successOr { - return Result.Failure(BlockchainSdkError.WrappedThrowable(it.error)) - } - atomicNonce.set(walletManager.txCount) - - return Result.Success(Unit) - } - - suspend fun sendTransactions(transactions: List): Result> { - val results = transactions.map { - coroutineScope { async { walletManager.sendRaw(it.compiledTransaction, it.signature) } } - }.awaitAll() - - val errors = results.filterIsInstance() - return if (errors.isEmpty()) { - Result.Success(listOf()) - } else { - Result.Failure(errors[0].error) - } - } - - suspend fun makeSetSpendLimitTx(value: BigDecimal): Result { - val limitAmount = Amount(walletManager.cardTokens.first(), value) - val feeAmount = walletManager.getFeeToSetSpendLimit(otpProcessorContractAddress, limitAmount) - .extractFeeAmount().successOr { return it } - - val compiledEthereumTransaction = walletManager.transactionBuilder.buildSetSpendLimitToSign( - processorContractAddress = otpProcessorContractAddress, - cardAddress = walletAddress, - amount = limitAmount, - transactionFee = feeAmount, - gasLimit = walletManager.gasLimitToSetSpendLimit, - nonce = atomicNonce.getAndIncrement().toBigInteger(), - ) ?: return Result.Failure(BlockchainSdkError.CustomError("Can't create the 'setSpendLimit' transaction")) - - return Result.Success(compiledEthereumTransaction) - } - - suspend fun makeInitOtpTx(rootOTP: ByteArray, rootOTPCounter: Int): Result { - val feeAmount = walletManager.getFeeToInitOTP(otpProcessorContractAddress, rootOTP, rootOTPCounter) - .extractFeeAmount().successOr { return it } - - val compiledEthereumTransaction = walletManager.transactionBuilder.buildInitOTPToSign( - processorContractAddress = otpProcessorContractAddress, - cardAddress = walletAddress, - otp = rootOTP, - otpCounter = rootOTPCounter, - transactionFee = feeAmount, - gasLimit = walletManager.gasLimitToInitOTP, - nonce = atomicNonce.getAndIncrement().toBigInteger(), - ) ?: return Result.Failure(BlockchainSdkError.CustomError("Can't create the 'initOtp' transaction")) - - return Result.Success(compiledEthereumTransaction) - } - - suspend fun makeSetWalletTx(): Result { - val feeAmount = walletManager.getFeeToSetWallet(otpProcessorContractAddress) - .extractFeeAmount().successOr { return it } - - val compiledEthereumTransaction = walletManager.transactionBuilder.buildSetWalletToSign( - processorContractAddress = otpProcessorContractAddress, - cardAddress = walletAddress, - transactionFee = feeAmount, - gasLimit = walletManager.gasLimitToSetWallet, - nonce = atomicNonce.getAndIncrement().toBigInteger(), - ) ?: return Result.Failure(BlockchainSdkError.CustomError("Can't create the 'setWallet' transaction")) - - return Result.Success(compiledEthereumTransaction) - } - - suspend fun makeApprovalTx(value: BigDecimal): Result { - val approveAmount = Amount(token, value) - val feeAmount = walletManager.getFeeToApprove(approveAmount, otpProcessorContractAddress) - .extractFeeAmount().successOr { return it } - - val compiledEthereumTransaction = walletManager.transactionBuilder.buildApproveToSign( - transactionData = walletManager.createTransaction( - amount = approveAmount, - fee = feeAmount, - destination = otpProcessorContractAddress, - ), - nonce = atomicNonce.getAndIncrement().toBigInteger(), - gasLimit = walletManager.gasLimitToApprove, - ) ?: return Result.Failure(BlockchainSdkError.CustomError("Can't create the 'approval' transaction")) - - return Result.Success(compiledEthereumTransaction) - } - - suspend fun getAllowance(): Result { - // return Result.Success(Amount(BigDecimal(0.1), walletManager.wallet.blockchain)) // test - return walletManager.getAllowance(addressTreasureSafe, token) - } - - suspend fun transferFrom(amountToClaim: BigDecimal, signer: TransactionSigner): Result { - if (walletManager.txCount == -1L) { - walletManager.safeUpdate().successOr { - return Result.Failure(BlockchainSdkError.WrappedThrowable(it.error)) - } - } - - // return transferFromStandardWay(amountToClaim, signer) - return transferFromHardcodeWay(amountToClaim, signer) - } - - @Suppress("UnusedPrivateMember") - private suspend fun transferFromStandardWay(amountToClaim: BigDecimal, signer: TransactionSigner): Result { - val amount = Amount(token, amountToClaim) - val feeAmount = walletManager.getFeeToTransferFrom(amount, addressTreasureSafe) - .extractFeeAmount().successOr { return it } - - val transactionData = walletManager.createTransferFromTransaction(amount, feeAmount, addressTreasureSafe) - walletManager.transferFrom(transactionData, signer).successOr { return Result.Failure(it.error) } - - return Result.Success(Unit) - } - - private suspend fun transferFromHardcodeWay(amountToClaim: BigDecimal, signer: TransactionSigner): Result { - val amount = Amount(token, amountToClaim) - val gasPrice = walletManager.getGasPrice().successOr { return it } - - val hardcodeGasLimit = BigInteger("300000") - val hardcodeFeeValue = (hardcodeGasLimit * gasPrice).toBigDecimal( - scale = blockchain.decimals(), - mathContext = MathContext(blockchain.decimals(), RoundingMode.HALF_EVEN), - ).movePointLeft(blockchain.decimals()) - val hardcodeFeeAmount = Amount(hardcodeFeeValue, blockchain) - - val transactionData = walletManager.createTransferFromTransaction( - amount = amount, - fee = hardcodeFeeAmount, - source = addressTreasureSafe, - ) - val transactionToSign = walletManager.transactionBuilder.buildTransferFromToSign( - transactionData, - walletManager.txCount.toBigInteger(), - hardcodeGasLimit, - ) ?: return Result.Failure(BlockchainSdkError.CustomError("Not enough data")) - - return when (val result = walletManager.signAndSend(transactionToSign, signer)) { - SimpleResult.Success -> Result.Success(Unit) - is SimpleResult.Failure -> Result.Failure(result.error) - } - } - - @Suppress("MagicNumber") - private fun Result>.extractFeeAmount(): Result { - return when (this) { - is Result.Success -> { - if (this.data.size != 3) { - Result.Failure(BlockchainSdkError.FailedToLoadFee) - } else { - Result.Success(this.data[1]) - } - } - is Result.Failure -> this - } - } - - private fun Long?.toBigInteger(): BigInteger? = this?.let { BigInteger.valueOf(it) } - - private fun Long.toBigInteger(): BigInteger = BigInteger.valueOf(this) - - companion object { - fun stub(): GnosisRegistrator { - return GnosisRegistrator(WalletManager.stub()) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/PinFilters.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/PinFilters.kt deleted file mode 100644 index fd359c25a4..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/PinFilters.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay - -import com.tangem.common.Filter - -/** -[REDACTED_AUTHOR] - */ -interface PinFilter : Filter - -class AllSymbolsTheSameFilter : PinFilter { - override fun filter(value: String): Boolean { - if (value.isEmpty()) return false - - val array = value.toCharArray() - val firstSymbol = array[0] - return array.all { it == firstSymbol } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayActivationManager.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayActivationManager.kt deleted file mode 100644 index 2f7f824f6c..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayActivationManager.kt +++ /dev/null @@ -1,341 +0,0 @@ -@file:Suppress("MaximumLineLength") - -package com.tangem.tap.features.onboarding.products.wallet.saltPay - -import android.net.Uri -import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager -import com.tangem.blockchain.blockchains.ethereum.SignedEthereumTransaction -import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.BlockchainSdkError -import com.tangem.blockchain.common.Token -import com.tangem.blockchain.common.TransactionSigner -import com.tangem.blockchain.common.Wallet -import com.tangem.blockchain.common.WalletManagerFactory -import com.tangem.blockchain.extensions.successOr -import com.tangem.common.core.TangemSdkError -import com.tangem.common.extensions.guard -import com.tangem.common.extensions.hexToBytes -import com.tangem.common.extensions.isZero -import com.tangem.common.extensions.toHexString -import com.tangem.common.services.Result -import com.tangem.common.services.performRequest -import com.tangem.datasource.api.paymentology.PaymentologyApiService -import com.tangem.datasource.api.paymentology.models.request.CheckRegistrationRequests -import com.tangem.datasource.api.paymentology.models.request.RegisterKYCRequest -import com.tangem.datasource.api.paymentology.models.request.RegisterWalletRequest -import com.tangem.datasource.api.paymentology.models.response.AttestationResponse -import com.tangem.datasource.api.paymentology.models.response.RegisterWalletResponse -import com.tangem.datasource.api.paymentology.models.response.RegistrationResponse -import com.tangem.datasource.api.paymentology.models.response.tryExtractError -import com.tangem.datasource.config.models.KYCProvider -import com.tangem.datasource.config.models.SaltPayConfig -import com.tangem.domain.models.scan.CardDTO -import com.tangem.domain.common.SaltPayWorkaround -import com.tangem.domain.common.extensions.successOr -import com.tangem.operations.attestation.AttestWalletKeyResponse -import com.tangem.tap.common.extensions.safeUpdate -import com.tangem.tap.domain.getFirstToken -import com.tangem.tap.domain.model.builders.UserWalletIdBuilder -import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError -import com.tangem.tap.store -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import java.math.BigDecimal -import kotlin.ByteArray -import kotlin.Exception -import kotlin.IllegalStateException -import kotlin.NullPointerException -import kotlin.String -import kotlin.Suppress -import kotlin.Unit -import kotlin.UnsupportedOperationException -import kotlin.byteArrayOf -import kotlin.minus -import com.tangem.blockchain.extensions.Result as BlockchainResult - -/** -[REDACTED_AUTHOR] - */ -class SaltPayActivationManager( - val cardId: String, - val cardPublicKey: ByteArray, - private val kycProvider: KYCProvider, - private val paymentologyService: PaymentologyApiService, - private val gnosisRegistrator: GnosisRegistrator, -) { - - val walletPublicKey = gnosisRegistrator.walletManager.wallet.publicKey.seedKey - val kycUrlProvider = KYCUrlProvider(walletPublicKey, kycProvider) - - private val approvalValue: BigDecimal = BigDecimal(2).pow(256).minus(BigDecimal.ONE) - .movePointLeft(gnosisRegistrator.walletManager.wallet.blockchain.decimals()) - - private val spendLimitValue: BigDecimal = BigDecimal("100") - - suspend fun checkHasGas(): Result { - return when (val hasGasResult = gnosisRegistrator.checkHasGas()) { - is BlockchainResult.Success -> if (hasGasResult.data) { - Result.Success(Unit) - } else { - Result.Failure(SaltPayActivationError.NoGas) - } - is BlockchainResult.Failure -> Result.Failure(hasGasResult.error as BlockchainSdkError) - } - } - - suspend fun registerKYC(): Result { - val result = withContext(Dispatchers.IO) { - performRequest { paymentologyService.api.registerKYC(makeRegisterKYCRequest()) } - } - return when (result) { - is Result.Success -> Result.Success(Unit) - is Result.Failure -> result - } - } - - suspend fun checkRegistration(): Result { - val requestItem = CheckRegistrationRequests.Item(cardId, cardPublicKey.toHexString()) - val request = CheckRegistrationRequests(listOf(requestItem)) - - val response: RegistrationResponse = withContext(Dispatchers.IO) { - performRequest { - paymentologyService.api.checkRegistration(request) - } - } - .successOr { return it } - .tryExtractError() - .successOr { return it } - - return try { - if (response.results.isEmpty()) throw SaltPayActivationError.EmptyResponse - - val item = response.results[0] - if (item.error != null) throw IllegalStateException(response.makeErrorMessage()) - - Result.Success(item) - } catch (ex: Exception) { - Result.Failure(ex) - } - } - - suspend fun requestAttestationChallenge(): Result { - val requestItem = CheckRegistrationRequests.Item(cardId, cardPublicKey.toHexString()) - return withContext(Dispatchers.IO) { - performRequest { - paymentologyService.api.requestAttestationChallenge(requestItem) - } - } - .successOr { return it } - .tryExtractError() - } - - suspend fun sendTransactions(signedTransactions: List): BlockchainResult> { - return gnosisRegistrator.sendTransactions(signedTransactions) - } - - suspend fun registerWallet( - attestResponse: AttestWalletKeyResponse, - pinCode: String, - ): Result { - val request = RegisterWalletRequest( - cardId = cardId, - publicKey = cardPublicKey, - walletPublicKey = walletPublicKey, - walletSalt = attestResponse.salt, - walletSignature = attestResponse.walletSignature, - cardSalt = attestResponse.publicKeySalt ?: byteArrayOf(), - cardSignature = attestResponse.cardSignature ?: byteArrayOf(), - pin = pinCode, - ) - return withContext(Dispatchers.IO) { - performRequest { - paymentologyService.api.registerWallet(request) - } - } - .successOr { return it } - .tryExtractError() - } - - suspend fun getAmountToClaim(): Result { - val amount = gnosisRegistrator.getAllowance().successOr { - return Result.Failure(SaltPayActivationError.FailedToGetFundsToClaim) - } - - return if (amount.value == null || amount.value?.isZero() == true) { - Result.Failure(SaltPayActivationError.NoFundsToClaim) - } else { - Result.Success(amount) - } - } - - suspend fun claim(amountToClaim: BigDecimal, signer: TransactionSigner): Result { - gnosisRegistrator.transferFrom(amountToClaim, signer).successOr { - val userCancelledError = (it.error as? BlockchainSdkError.WrappedTangemError) - ?.tangemError as? TangemSdkError.UserCancelled - - return when (userCancelledError) { - null -> Result.Failure(SaltPayActivationError.ClaimTransactionFailed) - else -> Result.Failure(userCancelledError) - } - } - return Result.Success(Unit) - } - - suspend fun getTokenAmount(): Result { - val wallet = gnosisRegistrator.walletManager.safeUpdate().successOr { return it } - val token = wallet.getFirstToken().guard { - throw UnsupportedOperationException() - } - - val amountValue = wallet.amounts[AmountType.Token(token)]?.value.guard { - throw UnsupportedOperationException() - } - - return Result.Success(amountValue) - } - - fun makeRegistrationTask(challenge: ByteArray): SaltPayRegistrationTask { - return SaltPayRegistrationTask( - gnosisRegistrator = gnosisRegistrator, - challenge = challenge, - walletPublicKey = walletPublicKey, - approvalValue = approvalValue, - spendLimitValue = spendLimitValue, - ) - } - - private fun makeRegisterKYCRequest(): RegisterKYCRequest = RegisterKYCRequest( - cardId = cardId, - publicKey = cardPublicKey, - kycProvider = "UTORG", - kycRefId = kycUrlProvider.kycRefId, - ) - - companion object { - fun stub(): SaltPayActivationManager = SaltPayActivationManager( - kycProvider = SaltPayConfig.stub().kycProvider, - paymentologyService = PaymentologyApiService, - gnosisRegistrator = GnosisRegistrator.stub(), - cardId = "", - cardPublicKey = byteArrayOf(), - ) - } -} - -class KYCUrlProvider( - walletPublicKey: ByteArray, - kycProvider: KYCProvider, -) { - - val kycRefId = UserWalletIdBuilder.walletPublicKey(walletPublicKey).stringValue - - val requestUrl: String = makeWebRequestUrl(kycProvider) - - val doneUrl = "https://success.tangem.com/" - - private fun makeWebRequestUrl(kycProvider: KYCProvider): String { - val baseUri = Uri.parse(kycProvider.baseUrl) - return Uri.Builder() - .scheme(baseUri.scheme) - .authority(baseUri.authority) - .encodedPath(baseUri.path) - .appendQueryParameter(kycProvider.sidParameterKey, kycProvider.sidValue) - .appendQueryParameter(kycProvider.externalIdParameterKey, kycRefId) - .build().toString() - } -} - -class SaltPayActivationManagerFactory( - private val blockchain: Blockchain, - private val card: CardDTO, -) { - - fun create(): SaltPayActivationManager { - val wallet = card.wallets.first() - val saltPayConfig = store.state.globalState.configManager?.config?.saltPayConfig.guard { - throw NullPointerException("SaltPayConfig is not initialized") - } - val wmFactory = store.state.globalState.tapWalletManager.walletManagerFactory - val paymentologyService = store.state.domainNetworks.paymentologyService - - // return createDummyActivationManager(saltPayConfig, wmFactory, paymentologyService) - return createActivationPayManager( - cardId = card.cardId, - cardPublicKey = card.cardPublicKey, - kycProvider = saltPayConfig.kycProvider, - gnosisRegistrator = GnosisRegistrator( - walletManager = makeSaltPayWalletManager( - blockchain = blockchain, - walletPublicKey = wallet.publicKey, - wmFactory = wmFactory, - ), - ), - paymentologyService = paymentologyService, - ) - } - - private fun makeSaltPayWalletManager( - blockchain: Blockchain, - walletPublicKey: ByteArray, - wmFactory: WalletManagerFactory, - ): EthereumWalletManager { - return wmFactory.makeWalletManager( - blockchain = blockchain, - publicKey = Wallet.PublicKey(walletPublicKey, null, null), - tokens = listOf(SaltPayWorkaround.tokenFrom(blockchain)), - ) as EthereumWalletManager - } - - private fun createActivationPayManager( - cardId: String, - cardPublicKey: ByteArray, - kycProvider: KYCProvider, - gnosisRegistrator: GnosisRegistrator, - paymentologyService: PaymentologyApiService, - ): SaltPayActivationManager { - return SaltPayActivationManager( - cardId = cardId, - cardPublicKey = cardPublicKey, - kycProvider = kycProvider, - paymentologyService = paymentologyService, - gnosisRegistrator = gnosisRegistrator, - ) - } - - @Suppress("UnusedPrivateMember") - private fun createDummyActivationManager( - saltPayConfig: SaltPayConfig, - wmFactory: WalletManagerFactory, - paymentologyService: PaymentologyApiService, - ): SaltPayActivationManager { - val fakeSource = DummySaltPayCardSource() - - val walletManager = wmFactory.makeWalletManager( - blockchain = fakeSource.blockchain, - publicKey = fakeSource.blockchainPublicKey, - tokens = listOf(fakeSource.token), - ) as EthereumWalletManager - - return createActivationPayManager( - cardId = fakeSource.cardId, - cardPublicKey = fakeSource.cardPublicKey, - kycProvider = saltPayConfig.kycProvider, - gnosisRegistrator = GnosisRegistrator(walletManager), - paymentologyService = paymentologyService, - ) - } - - private data class DummySaltPayCardSource( - val blockchain: Blockchain = Blockchain.SaltPay, - val cardId: String = "FF03000001001057", - private val cardPublicKeyString: String = "039C2D2F9B68003766BFC29766761F55F4084E48B8B012BF439E115A79AB122D48", - private val walletPublicKeyString: String = "0399B2DF5B129FBF69097DAA7C44FB5849E578CCFC22228A409870C74B56C4C3D1", - ) { - val cardPublicKey: ByteArray = cardPublicKeyString.hexToBytes() - val walletPublicKey: ByteArray = walletPublicKeyString.hexToBytes() - val blockchainPublicKey = Wallet.PublicKey(walletPublicKey, null, null) - val token: Token = SaltPayWorkaround.tokenFrom(blockchain) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayExceptionHandler.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayExceptionHandler.kt deleted file mode 100644 index 8d116a7385..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayExceptionHandler.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay - -import com.tangem.blockchain.common.BlockchainSdkError -import com.tangem.common.core.TangemSdkError -import com.tangem.core.analytics.Analytics -import com.tangem.tap.common.analytics.events.Onboarding -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.SaltPayActivationError -import com.tangem.tap.store - -/** -[REDACTED_AUTHOR] - */ -object SaltPayExceptionHandler { - - fun handle(throwable: Throwable) { - when (throwable) { - is SaltPayActivationError -> { - val dialog = when (throwable) { - is SaltPayActivationError.NoGas -> { - Analytics.send(Onboarding.NotEnoughGasError()) - SaltPayDialog.Activation.NoGas - } - is SaltPayActivationError.PutVisaCard -> SaltPayDialog.Activation.PutVisaCard - is SaltPayActivationError.CardNotPassed -> { - Analytics.send(Onboarding.CardNotPassedError()) - SaltPayDialog.Activation.OnError(throwable) - } - else -> SaltPayDialog.Activation.OnError(throwable) - } - store.dispatchDialogShow(dialog) - } - is TangemSdkError -> { - when (throwable) { - is TangemSdkError.NetworkError -> { - val message = throwable.customMessage - store.dispatchDialogShow(AppDialog.SimpleOkErrorDialog(message)) - } - else -> Unit - } - } - is BlockchainSdkError -> { - store.dispatchDialogShow(AppDialog.SimpleOkErrorDialog(throwable.customMessage)) - } - else -> { - val message = throwable.localizedMessage ?: "SaltPay unknown error" - store.dispatchDialogShow(AppDialog.SimpleOkErrorDialog(message)) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayRegistrationTask.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayRegistrationTask.kt deleted file mode 100644 index fb4bd50ed9..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayRegistrationTask.kt +++ /dev/null @@ -1,167 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay - -import com.tangem.blockchain.blockchains.ethereum.CompiledEthereumTransaction -import com.tangem.blockchain.blockchains.ethereum.SignedEthereumTransaction -import com.tangem.blockchain.extensions.successOr -import com.tangem.common.CompletionResult -import com.tangem.common.core.CardSession -import com.tangem.common.core.CardSessionRunnable -import com.tangem.common.core.CompletionCallback -import com.tangem.common.core.TangemSdkError -import com.tangem.common.extensions.guard -import com.tangem.operations.CommandResponse -import com.tangem.operations.GenerateOTPCommand -import com.tangem.operations.GenerateOTPResponse -import com.tangem.operations.attestation.AttestWalletKeyCommand -import com.tangem.operations.attestation.AttestWalletKeyResponse -import com.tangem.operations.sign.SignHashesCommand -import com.tangem.tap.scope -import kotlinx.coroutines.launch -import java.math.BigDecimal - -/** -[REDACTED_AUTHOR] - */ -data class RegistrationTaskResponse( - val signedTransactions: List, - val attestResponse: AttestWalletKeyResponse, -) : CommandResponse - -class SaltPayRegistrationTask( - private var gnosisRegistrator: GnosisRegistrator, - private var challenge: ByteArray, - private val walletPublicKey: ByteArray, - private val approvalValue: BigDecimal, - private val spendLimitValue: BigDecimal, -) : CardSessionRunnable { - - private var generateOTPResponse: GenerateOTPResponse? = null - private var attestWalletResponse: AttestWalletKeyResponse? = null - private var signedTransactions: List = listOf() - - override fun run(session: CardSession, callback: CompletionCallback) { - generateOTP(session, callback) - } - - private fun generateOTP(session: CardSession, callback: CompletionCallback) { - GenerateOTPCommand().run(session) { result -> - when (result) { - is CompletionResult.Success -> { - generateOTPResponse = result.data - attestWallet(session, callback) - } - is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) - } - } - } - - private fun attestWallet(session: CardSession, callback: CompletionCallback) { - val card = session.environment.card.guard { - callback(CompletionResult.Failure(TangemSdkError.MissingPreflightRead())) - return - } - - val walletPublicKey = card.wallets.firstOrNull()?.publicKey - if (walletPublicKey == null || !walletPublicKey.contentEquals(this.walletPublicKey)) { - callback(CompletionResult.Failure(TangemSdkError.WalletNotFound())) - return - } - - val attestWalletCommand = AttestWalletKeyCommand( - publicKey = walletPublicKey, - challenge = challenge, - confirmationMode = AttestWalletKeyCommand.ConfirmationMode.Dynamic, - ) - attestWalletCommand.run(session) { result -> - when (result) { - is CompletionResult.Success -> { - attestWalletResponse = result.data - scope.launch { prepareTransactions(session, callback) } - } - is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) - } - } - } - - private suspend fun prepareTransactions( - session: CardSession, - callback: CompletionCallback, - ) { - val generateOTPResponse = this.generateOTPResponse.guard { - callback(CompletionResult.Failure(TangemSdkError.UnknownError())) - return - } - - gnosisRegistrator.prepareBeforeMakingTxs().successOr { - callback(CompletionResult.Failure(it.error)) - return - } - - val approvalTx = gnosisRegistrator.makeApprovalTx(approvalValue).successOr { - callback(CompletionResult.Failure(it.error)) - return - } - val setWalletTx = gnosisRegistrator.makeSetWalletTx().successOr { - callback(CompletionResult.Failure(it.error)) - return - } - val initOtpTx = gnosisRegistrator.makeInitOtpTx( - generateOTPResponse.rootOTP, - generateOTPResponse.rootOTPCounter, - ).successOr { - callback(CompletionResult.Failure(it.error)) - return - } - - val setSpendLimitTx = gnosisRegistrator.makeSetSpendLimitTx(spendLimitValue).successOr { - callback(CompletionResult.Failure(it.error)) - return - } - - signTransactions( - transactions = listOf( - approvalTx, - setWalletTx, - initOtpTx, - setSpendLimitTx, - ), - session = session, - callback = callback, - ) - } - - private fun signTransactions( - transactions: List, - session: CardSession, - callback: CompletionCallback, - ) { - val walletPublicKey = session.environment.card?.wallets?.firstOrNull()?.publicKey.guard { - callback(CompletionResult.Failure(TangemSdkError.WalletNotFound())) - return - } - - val hashes = transactions.map { it.hash }.toTypedArray() - val signHashesCommand = SignHashesCommand(hashes, walletPublicKey) - - signHashesCommand.run(session) { result -> - when (result) { - is CompletionResult.Success -> { - signedTransactions = transactions.zip(result.data.signatures).map { - SignedEthereumTransaction(it.first, it.second) - } - complete(callback) - } - is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) - } - } - } - - private fun complete(callback: CompletionCallback) { - if (signedTransactions.isEmpty() || attestWalletResponse == null) { - callback(CompletionResult.Failure(TangemSdkError.UnknownError())) - } else { - val result = RegistrationTaskResponse(signedTransactions, attestWalletResponse!!) - callback(CompletionResult.Success(result)) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/UtorgWebView.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/UtorgWebView.kt deleted file mode 100644 index 2a33de86f4..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/UtorgWebView.kt +++ /dev/null @@ -1,168 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay - -import android.app.Activity -import android.content.Intent -import android.net.Uri -import android.provider.MediaStore -import android.text.TextUtils -import android.webkit.PermissionRequest -import android.webkit.ValueCallback -import android.webkit.WebChromeClient -import android.webkit.WebResourceRequest -import android.webkit.WebView -import android.webkit.WebViewClient -import androidx.activity.ComponentActivity -import androidx.core.app.ActivityCompat -import com.tangem.tap.common.ActivityResultCallbackHolder -import com.tangem.tap.common.OnActivityResultCallback -import com.tangem.tap.common.extensions.dispatchDialogShow -import com.tangem.tap.common.extensions.isPermissionGranted -import com.tangem.tap.common.redux.AppDialog -import com.tangem.tap.store -import com.tangem.wallet.R -import java.io.File - -/** -[REDACTED_AUTHOR] - */ -class UtorgWebViewClient( - private val onSuccess: () -> Unit, - private val successUrl: String, -) : WebViewClient() { - - override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean = - if (successUrl == request.url.toString()) { - onSuccess() - true - } else { - false - } -} - -class UtorgWebChromeClient( - private val activity: ComponentActivity, - private val activityResultCallbackHolder: ActivityResultCallbackHolder = activity as ActivityResultCallbackHolder, -) : WebChromeClient() { - - private val fileChooseRequestCode = 1002 - private val permissionRequestCode = 1003 - private val onActivityResultCallback: OnActivityResultCallback = ::onActivityResult - - private val permissionList = listOf( - "android.permission.CAMERA", - ) - - private var filePathCallback: ValueCallback>? = null - private var mediaUri: Uri? = null - - override fun onShowFileChooser( - webView: WebView?, - filePathCallback: ValueCallback>, - fileChooserParams: FileChooserParams?, - ): Boolean { - activityResultCallbackHolder.addOnActivityResultCallback(onActivityResultCallback) - if (!readyToShowFileChooser()) return false - - val type: String - if (fileChooserParams != null && fileChooserParams.acceptTypes != null && - fileChooserParams.acceptTypes.isNotEmpty() - ) { - type = if (!TextUtils.isEmpty(fileChooserParams.acceptTypes[0])) fileChooserParams.acceptTypes[0] else "*/*" - this.filePathCallback = filePathCallback - } else { - return false - } - proceedOnType(type, fileChooserParams.isCaptureEnabled) - - return true - } - - private fun readyToShowFileChooser(): Boolean { - val permissionsToGrant = permissionList.filterNot { activity.isPermissionGranted(it) }.toTypedArray() - return if (permissionsToGrant.isNotEmpty()) { - ActivityCompat.requestPermissions(activity, permissionsToGrant, permissionRequestCode) - false - } else { - true - } - } - - private fun proceedOnType(type: String, isCaptureEnabled: Boolean) { - if (isCaptureEnabled) { - mediaUri = Uri.fromFile(File(getImageCaptureCachePath())) - val imageCaptureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) - imageCaptureIntent.putExtra("output", mediaUri) - activity.startActivityForResult( - Intent.createChooser(imageCaptureIntent, "Image Chooser"), - fileChooseRequestCode, - ) - } else { - mediaUri = Uri.fromFile(File(getImageCaptureCachePath())) - - val getContentIntent = Intent(Intent.ACTION_GET_CONTENT) - getContentIntent.addCategory(Intent.CATEGORY_OPENABLE) - getContentIntent.type = "image/*" - - // val imageCaptureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) - // imageCaptureIntent.putExtra("output", mediaUri) - - val chooserIntent = Intent.createChooser(getContentIntent, "Pick a photo") - // chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(imageCaptureIntent)) - - activity.startActivityForResult( - Intent.createChooser(chooserIntent, "Image Chooser"), - fileChooseRequestCode, - ) - } - } - - private fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - when (requestCode) { - fileChooseRequestCode -> { - if (resultCode != Activity.RESULT_OK) { - filePathCallback?.onReceiveValue(null) - clean() - return - } - if (data == null) { - filePathCallback?.onReceiveValue(arrayOf(mediaUri!!)) - } else { - val uri = FileChooserParams.parseResult(resultCode, data) - filePathCallback?.onReceiveValue(uri) - } - clean() - } - permissionRequestCode -> { - val notGranted = permissionList.filterNot { activity.isPermissionGranted(it) } - if (notGranted.isNotEmpty()) { - val permissionsName = notGranted.joinToString("\n") { it.permissionName() } - store.dispatchDialogShow( - AppDialog.SimpleOkDialog( - header = activity.getString(R.string.common_warning), - message = "Permission access is required to pass authorization." + - "To grant permission \n" + - "$permissionsName \n" + - "you must enable them in the app's settings", - ), - ) - } - } - } - } - - override fun onPermissionRequest(request: PermissionRequest) { - request.grant(request.resources) - } - - private fun getImageCaptureCachePath(): String = "cached_photo_" + System.currentTimeMillis() + ".jpg" - - private fun clean() { - activityResultCallbackHolder.removeOnActivityResultCallback(onActivityResultCallback) - filePathCallback = null - mediaUri = null - } - - private fun String.permissionName(): String { - return this.slice(this.lastIndexOf(".") until this.length) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/NoFundsForActivationDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/NoFundsForActivationDialog.kt deleted file mode 100644 index 5121db94db..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/NoFundsForActivationDialog.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog - -import android.app.Dialog -import android.content.Context -import androidx.appcompat.app.AlertDialog -import com.tangem.common.extensions.guard -import com.tangem.tap.common.extensions.dispatchDebugErrorNotification -import com.tangem.tap.common.feedback.SupportInfo -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.store -import com.tangem.wallet.R - -/** -[REDACTED_AUTHOR] - */ -object NoFundsForActivationDialog { - - fun create(context: Context): Dialog { - return AlertDialog.Builder(context).apply { - setTitle(R.string.saltpay_error_no_gas_title) - setMessage(R.string.saltpay_error_no_gas_message) - setPositiveButton(R.string.chat_button_title) { _, _ -> - val sprinklrConfig = store.state.globalState.configManager?.config - ?.saltPayConfig - ?.sprinklr - .guard { - store.dispatchDebugErrorNotification("SaltPayConfig not initialized") - return@setPositiveButton - } - store.dispatch(GlobalAction.OpenChat(SupportInfo(), sprinklrConfig)) - } - setNegativeButton(R.string.common_cancel) { _, _ -> - } - setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) - } - setCancelable(false) - }.create() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/PutVisaCardDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/PutVisaCardDialog.kt deleted file mode 100644 index d3daf798fe..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/PutVisaCardDialog.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog - -import android.app.Dialog -import android.content.Context -import androidx.appcompat.app.AlertDialog -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.store -import com.tangem.wallet.R - -/** -[REDACTED_AUTHOR] - */ -object PutVisaCardDialog { - fun create(context: Context): Dialog { - return AlertDialog.Builder(context).apply { - setTitle(R.string.saltpay_error_empty_backup_title) - setMessage(R.string.saltpay_error_empty_backup_message) - setPositiveButton(R.string.common_ok) { _, _ -> } - setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) - } - setCancelable(false) - }.create() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/RegistrationErrorDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/RegistrationErrorDialog.kt deleted file mode 100644 index f3c184157f..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/RegistrationErrorDialog.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog - -import android.app.Dialog -import android.content.Context -import androidx.appcompat.app.AlertDialog -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.domain.moduleMessage.ConvertedDialogMessage -import com.tangem.tap.domain.moduleMessage.saltPay.SaltPayErrorConverter -import com.tangem.tap.store -import com.tangem.wallet.R - -/** -[REDACTED_AUTHOR] - */ -object RegistrationErrorDialog { - fun create(context: Context, dialog: SaltPayDialog.Activation.OnError): Dialog { - val convertedMessage = SaltPayErrorConverter(context).convert(dialog.error) as ConvertedDialogMessage - - return AlertDialog.Builder(context).apply { - setTitle(convertedMessage.title) - setMessage(convertedMessage.message) - setPositiveButton(R.string.common_ok) { _, _ -> - store.dispatch(GlobalAction.HideDialog) - } - setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) - } - setCancelable(false) - }.create() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/SaltPayDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/SaltPayDialog.kt deleted file mode 100644 index 26228ba27f..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/SaltPayDialog.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog - -import com.tangem.tap.common.redux.StateDialog -import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError - -/** -[REDACTED_AUTHOR] - */ -sealed class SaltPayDialog : StateDialog { - sealed class Activation : SaltPayDialog() { - object NoGas : SaltPayDialog() - object PutVisaCard : SaltPayDialog() - data class OnError(val error: SaltPayActivationError) : SaltPayDialog() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/message/SaltPayModuleMessage.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/message/SaltPayModuleMessage.kt deleted file mode 100644 index c6e8d9526e..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/message/SaltPayModuleMessage.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay.message - -import com.tangem.common.module.ModuleError -import com.tangem.common.module.ModuleErrorCode -import com.tangem.common.module.ModuleMessage - -sealed interface SaltPayModuleMessage : ModuleMessage - -sealed class SaltPayModuleError( - subCode: Int, - override val message: String, - override val data: Any? = null, -) : SaltPayModuleMessage, ModuleError() { - override val code: Int = ModuleErrorCode.SALT_PAY + subCode - - companion object { - // base code used for all errors in the module - internal const val ERROR_CODE_REGISTRATION = 100 -// const val CODE_ANY_OTHER = 200..299, 300..399 etc - } -} - -sealed class SaltPayActivationError( - subCode: Int, - message: String? = null, - override val data: Any? = null, -) : SaltPayModuleError( - subCode = ERROR_CODE_REGISTRATION + subCode, - message = message ?: EMPTY_MESSAGE, -) { - object Unknown : SaltPayActivationError(subCode = 4) - object Empty : SaltPayActivationError(subCode = 4) - - // gnosis - object FailedToMakeTxData : SaltPayActivationError(subCode = 1) - object FailedToSendTx : SaltPayActivationError(subCode = 2) - - object NeedPin : SaltPayActivationError(subCode = 3) - object NoGas : SaltPayActivationError(subCode = 5) - object EmptyResponse : SaltPayActivationError(subCode = 6) - object CardNotFound : SaltPayActivationError(subCode = 8) - class CardDisabled(message: String?) : SaltPayActivationError(subCode = 9, message = message) - class CardNotPassed(message: String?) : SaltPayActivationError(subCode = 10, message = message) - object EmptyDynamicAttestResponse : SaltPayActivationError(subCode = 11) - object EmptyBackupCardScanned : SaltPayActivationError(subCode = 12) - object WeakPin : SaltPayActivationError(subCode = 13) - - object FailedToGetFundsToClaim : SaltPayActivationError(subCode = 14) - object NoFundsToClaim : SaltPayActivationError(subCode = 15) - object ClaimTransactionFailed : SaltPayActivationError(subCode = 16) - object PutVisaCard : SaltPayActivationError(subCode = 18) - - companion object { - const val EMPTY_MESSAGE = "" - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayAction.kt deleted file mode 100644 index 91b791925d..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayAction.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay.redux - -import com.tangem.blockchain.common.Amount -import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager -import org.rekotlin.Action -import java.math.BigDecimal - -/** -[REDACTED_AUTHOR] - */ -sealed class OnboardingSaltPayAction : Action { - object Init : OnboardingSaltPayAction() - - /** - * Notification about the switching from the Wallet view to the SaltPay view. - */ - object OnSwitchedToSaltPayProcess : OnboardingSaltPayAction() - - data class SetDependencies( - val registrationManager: SaltPayActivationManager, - ) : OnboardingSaltPayAction() - - data class SetInProgress(val isInProgress: Boolean) : OnboardingSaltPayAction() - data class SetClaimRefreshInProgress(val isInProgress: Boolean) : OnboardingSaltPayAction() - - data class SetAccessCode(val accessCode: String?) : OnboardingSaltPayAction() - - data class Update(val withAnalytics: Boolean = true) : OnboardingSaltPayAction() - object RegisterCard : OnboardingSaltPayAction() - object OpenUtorgKYC : OnboardingSaltPayAction() - object UtorgKYCRedirectSuccess : OnboardingSaltPayAction() - object RegisterKYC : OnboardingSaltPayAction() - object Claim : OnboardingSaltPayAction() - object RefreshClaim : OnboardingSaltPayAction() - - data class TrySetPin(val pin: String) : OnboardingSaltPayAction() - data class SetPin(val pin: String) : OnboardingSaltPayAction() - - data class SetStep( - val newStep: SaltPayActivationStep, - val withAnalytics: Boolean = true, - ) : OnboardingSaltPayAction() - - data class SetAmountToClaim(val amount: Amount?) : OnboardingSaltPayAction() - data class SetTokenBalance(val balanceValue: BigDecimal) : OnboardingSaltPayAction() -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayMiddleware.kt deleted file mode 100644 index 5418a8d42e..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayMiddleware.kt +++ /dev/null @@ -1,466 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay.redux - -import com.tangem.Message -import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.extensions.successOr -import com.tangem.common.Filter -import com.tangem.common.core.TangemSdkError -import com.tangem.common.extensions.guard -import com.tangem.common.services.Result -import com.tangem.core.analytics.Analytics -import com.tangem.datasource.api.paymentology.models.response.KYCStatus -import com.tangem.datasource.api.paymentology.models.response.RegistrationResponse -import com.tangem.domain.common.extensions.successOr -import com.tangem.domain.common.extensions.withMainContext -import com.tangem.tap.common.analytics.events.Onboarding -import com.tangem.tap.common.extensions.dispatchDebugErrorNotification -import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.common.extensions.isPositive -import com.tangem.tap.common.redux.AppState -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.domain.TangemSigner -import com.tangem.tap.features.demo.DemoHelper -import com.tangem.tap.features.onboarding.OnboardingManager -import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState -import com.tangem.tap.features.onboarding.products.wallet.redux.finishCardActivation -import com.tangem.tap.features.onboarding.products.wallet.redux.gatherCardIds -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.SaltPayActivationError -import com.tangem.tap.scope -import com.tangem.tap.store -import com.tangem.tap.tangemSdk -import com.tangem.tap.tangemSdkManager -import com.tangem.wallet.R -import kotlinx.coroutines.launch -import org.rekotlin.Action -import org.rekotlin.Middleware -import timber.log.Timber - -/** -[REDACTED_AUTHOR] - */ -object OnboardingSaltPayMiddleware { - val handler = onboardingSaltPayMiddleware -} - -private val onboardingSaltPayMiddleware: Middleware = { dispatch, state -> - { next -> - { action -> - handleOnboardingSaltPayAction(action, state) - next(action) - } - } -} - -@Suppress("LongMethod", "ComplexMethod") -private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> AppState?) { - if (DemoHelper.tryHandle(appState, anyAction)) return - val action = anyAction as? OnboardingSaltPayAction ?: return - appState() ?: return - - fun getAppState(): AppState = appState()!! - fun getOnboardingWalletState(): OnboardingWalletState = getAppState().onboardingWalletState - fun getOnboardingManager(): OnboardingManager? = getAppState().globalState.onboardingState.onboardingManager - fun getState(): OnboardingSaltPayState = getOnboardingWalletState().onboardingSaltPayState!! - - when (action) { - is OnboardingSaltPayAction.Init -> { - if (!getOnboardingWalletState().isSaltPay) return - val onboardingManager = getOnboardingManager().guard { - // onboardingManager may be null if it's started from standard Wallet unfinished backup - return - } - - val card = onboardingManager.scanResponse.card - if (!onboardingManager.isActivationStarted(card.cardId)) { - Analytics.send(Onboarding.Started()) - onboardingManager.activationStarted(card.cardId) - } - } - is OnboardingSaltPayAction.OnSwitchedToSaltPayProcess -> { - sendAnalyticsScreenOpened(SaltPayActivationStep.None, newStep = getState().step) - } - is OnboardingSaltPayAction.Update -> { - handleInProgress = true - - val state = getState() - scope.launch { - val updateStep = state.saltPayManager.update(state.step, state.amountToClaim).successOr { - onException(it.error) - return@launch - } - - handleInProgress = false - dispatchOnMain(OnboardingSaltPayAction.SetStep(updateStep, action.withAnalytics)) - - if (updateStep == SaltPayActivationStep.Claim) { - handleClaimRefreshInProgress = true - val tokenAmountValue = state.saltPayManager.getTokenAmount().successOr { - SaltPayExceptionHandler.handle(it.error) - handleClaimRefreshInProgress = false - return@launch - } - dispatchOnMain(OnboardingSaltPayAction.SetTokenBalance(tokenAmountValue)) - handleClaimRefreshInProgress = false - } - } - } - is OnboardingSaltPayAction.RegisterCard -> { - handleInProgress = true - val state = getState() - - scope.launch { - val saltPayManager = state.saltPayManager - checkGasIfNeeded(state.saltPayManager, state.step).successOr { - onException(it.error) - return@launch - } - - val pinCode = state.pinCode.guard { - onError(SaltPayActivationError.NeedPin) - return@launch - } - - val attestationResponse = saltPayManager.requestAttestationChallenge().successOr { - onException(it.error) - return@launch - } - - val registrationResponse = tangemSdkManager.runTaskAsync( - runnable = saltPayManager.makeRegistrationTask(attestationResponse.challenge!!), - cardId = saltPayManager.cardId, - initialMessage = Message( - header = null, - body = tangemSdkManager.getString(R.string.registration_task_alert_message), - ), - accessCode = state.accessCode, - ).successOr { - onException(it.error as Exception) - return@launch - } - - saltPayManager.sendTransactions(registrationResponse.signedTransactions).successOr { - onError(SaltPayActivationError.FailedToSendTx) - return@launch - } - - saltPayManager.registerWallet(registrationResponse.attestResponse, pinCode).successOr { - onException(it.error) - return@launch - } - - Analytics.send(Onboarding.PinCodeSet()) - - var nextStep = SaltPayActivationStep.KycIntro - nextStep = saltPayManager.update(nextStep, state.amountToClaim).successOr { - onException(it.error) - return@launch - } - - handleInProgress = false - dispatchOnMain(OnboardingSaltPayAction.SetStep(nextStep)) - } - } - is OnboardingSaltPayAction.OpenUtorgKYC -> { - store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycStart)) - } - is OnboardingSaltPayAction.UtorgKYCRedirectSuccess -> { - store.dispatch(OnboardingSaltPayAction.RegisterKYC) - } - is OnboardingSaltPayAction.RegisterKYC -> { - val state = getState() - store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycWaiting)) - handleInProgress = true - - scope.launch { - Timber.d("saltPayManager.registerKYC()") - state.saltPayManager.registerKYC().successOr { - onException(it.error) - return@launch - } - - handleInProgress = false - dispatchOnMain(OnboardingSaltPayAction.Update()) - } - } - is OnboardingSaltPayAction.TrySetPin -> { - try { - assertPinValid(action.pin, getState().pinLength) - Analytics.send(Onboarding.ButtonSetPinCode()) - store.dispatch(OnboardingSaltPayAction.SetPin(action.pin)) - store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.CardRegistration)) - } catch (error: SaltPayActivationError) { - SaltPayExceptionHandler.handle(error) - } - } - is OnboardingSaltPayAction.Claim -> { - val state = getState() - handleInProgress = true - - scope.launch { - val amountToClaim = getAmountToClaimIfNeeded(state.saltPayManager, state.amountToClaim).guard { - onException(SaltPayActivationError.NoFundsToClaim) - return@launch - } - - val scanResponse = store.state.globalState.scanResponse - ?: store.state.globalState.onboardingState.onboardingManager?.scanResponse - val signer = TangemSigner( - card = scanResponse!!.card, - tangemSdk = tangemSdk, - initialMessage = Message(), - accessCode = state.accessCode, - ) { signResponse -> - store.dispatch( - GlobalAction.UpdateWalletSignedHashes( - walletSignedHashes = signResponse.totalSignedHashes, - walletPublicKey = state.saltPayManager.walletPublicKey, - remainingSignatures = signResponse.remainingSignatures, - ), - ) - } - state.saltPayManager.claim(amountToClaim.value!!, signer).successOr { - dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.Claim)) - if (it.error is TangemSdkError.UserCancelled) { - handleInProgress = false - } else { - onException(it.error) - } - return@launch - } - - handleInProgress = false - Analytics.send(Onboarding.ClaimWasSuccessfully()) - dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.ClaimInProgress)) - dispatchOnMain(OnboardingSaltPayAction.RefreshClaim) - } - } - is OnboardingSaltPayAction.RefreshClaim -> { - handleClaimRefreshInProgress = true - - val state = getState() - scope.launch { - val tokenAmountValue = state.saltPayManager.getTokenAmount().successOr { - SaltPayExceptionHandler.handle(it.error) - handleClaimRefreshInProgress = false - return@launch - } - dispatchOnMain(OnboardingSaltPayAction.SetTokenBalance(tokenAmountValue)) - - val amountToClaim = state.saltPayManager.getAmountToClaim().successOr { - if (it.error !is SaltPayActivationError.NoFundsToClaim) { - handleClaimRefreshInProgress = false - SaltPayExceptionHandler.handle(it.error) - return@launch - } else { - null - } - } - handleClaimRefreshInProgress = false - - if (tokenAmountValue.isPositive() && amountToClaim == null) { - dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.ClaimSuccess)) - } else { - // dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.ClaimSuccess)) - } - } - } - is OnboardingSaltPayAction.SetStep -> { - if (action.withAnalytics) { - sendAnalyticsScreenOpened(getState().step, action.newStep) - } - if (action.newStep == SaltPayActivationStep.ClaimSuccess || - action.newStep == SaltPayActivationStep.Success - ) { - val onboardingManager = getOnboardingManager().guard { - // Null is possible if it is started from a standard pending backup and in this case - // it is impossible to get here - store.dispatchDebugErrorNotification("OnboardingManager can't be NULL") - return - } - val cardIds = gatherCardIds(getOnboardingWalletState().backupState, onboardingManager.scanResponse.card) - finishCardActivation(cardIds) - } - } - else -> { - /* do nothing, only reduce */ - } - } -} - -private fun sendAnalyticsScreenOpened(currentStep: SaltPayActivationStep, newStep: SaltPayActivationStep) { - if (currentStep == newStep) return - - when (newStep) { - SaltPayActivationStep.NeedPin -> Analytics.send(Onboarding.PinScreenOpened()) - SaltPayActivationStep.CardRegistration -> Analytics.send(Onboarding.CardConnectionScreenOpened()) - SaltPayActivationStep.KycIntro -> Analytics.send(Onboarding.KYCScreenOpened()) - SaltPayActivationStep.KycStart -> Analytics.send(Onboarding.KYCStarted()) - SaltPayActivationStep.KycWaiting -> Analytics.send(Onboarding.KYCInProgress()) - SaltPayActivationStep.KycReject -> Analytics.send(Onboarding.KYCRejected()) - SaltPayActivationStep.Claim -> Analytics.send(Onboarding.ClaimScreenOpened()) - SaltPayActivationStep.ClaimSuccess, SaltPayActivationStep.Success -> Analytics.send(Onboarding.Finished()) - else -> {} - } -} - -suspend fun SaltPayActivationManager.update( - currentStep: SaltPayActivationStep, - currentAmountToClaim: Amount?, -): Result { - Timber.d("updateSaltPayStatus") - - val registrationResponse = checkRegistration().successOr { return it } - val amountToClaim = getAmountToClaimIfNeeded(this, currentAmountToClaim) - dispatchOnMain(OnboardingSaltPayAction.SetAmountToClaim(amountToClaim)) - - val newStep = try { - determineStep(currentStep, amountToClaim, registrationResponse) - } catch (ex: Exception) { - return Result.Failure(ex) - } - - checkGasIfNeeded(this, newStep).successOr { return it } - - Timber.d("update: success: %s", newStep) - return Result.Success(newStep) -} - -@Suppress("ComplexMethod") -private fun determineStep( - currentStep: SaltPayActivationStep, - amountToClaim: Amount?, - response: RegistrationResponse.Item, -): SaltPayActivationStep { - fun getStepBaseOnAmountToClaim(amount: Amount?): SaltPayActivationStep = when (amount) { - null -> SaltPayActivationStep.Success - else -> SaltPayActivationStep.Claim - } - - return when { - response.passed != true -> throw SaltPayActivationError.CardNotPassed(response.error) - response.disabledByAdmin == true -> throw SaltPayActivationError.CardDisabled(response.error) - - // go to claim screen - response.active == true -> getStepBaseOnAmountToClaim(amountToClaim) - - // pinSet is false, go toPin screen - response.pinSet == false -> SaltPayActivationStep.NeedPin - - response.kycStatus != null -> { - when (currentStep) { - SaltPayActivationStep.KycWaiting -> when (response.kycStatus) { - KYCStatus.NOT_STARTED, KYCStatus.STARTED -> SaltPayActivationStep.KycIntro - KYCStatus.WAITING_FOR_APPROVAL -> SaltPayActivationStep.KycWaiting - KYCStatus.CORRECTION_REQUESTED, KYCStatus.REJECTED -> SaltPayActivationStep.KycReject - KYCStatus.APPROVED -> getStepBaseOnAmountToClaim(amountToClaim) - else -> SaltPayActivationStep.KycIntro - } - SaltPayActivationStep.KycReject -> when (response.kycStatus) { - KYCStatus.NOT_STARTED, KYCStatus.STARTED -> SaltPayActivationStep.KycStart - KYCStatus.WAITING_FOR_APPROVAL -> SaltPayActivationStep.KycWaiting - KYCStatus.CORRECTION_REQUESTED -> SaltPayActivationStep.KycStart - KYCStatus.REJECTED -> SaltPayActivationStep.KycStart - KYCStatus.APPROVED -> getStepBaseOnAmountToClaim(amountToClaim) - else -> SaltPayActivationStep.KycIntro - } - else -> when (response.kycStatus) { - KYCStatus.NOT_STARTED, KYCStatus.STARTED -> SaltPayActivationStep.KycIntro - KYCStatus.WAITING_FOR_APPROVAL -> SaltPayActivationStep.KycWaiting - KYCStatus.CORRECTION_REQUESTED, KYCStatus.REJECTED -> SaltPayActivationStep.KycReject - KYCStatus.APPROVED -> getStepBaseOnAmountToClaim(amountToClaim) - else -> SaltPayActivationStep.KycIntro - } - } - } - - // kycDate is set, go to kyc waiting screen - response.kycDate != null -> SaltPayActivationStep.KycWaiting - - else -> SaltPayActivationStep.KycIntro - } -} - -private suspend fun getAmountToClaimIfNeeded( - saltPayManager: SaltPayActivationManager, - amountToClaim: Amount?, -): Amount? { - Timber.d("getAmountToClaimIfNeeded: for amount: %s", amountToClaim) - if (amountToClaim != null) { - Timber.d("getAmountToClaimIfNeeded: checks no need, amount already persist") - return amountToClaim - } - - // return Amount(BigDecimal(0.1), Blockchain.SaltPay) - return when (val result = saltPayManager.getAmountToClaim()) { - is Result.Success -> { - Timber.d("getAmountToClaimIfNeeded: success: %s", result.data) - return result.data - } - is Result.Failure -> { - Timber.e(result.error, "getAmountToClaimIfNeeded: failure") - null - } - } -} - -private var handleClaimRefreshInProgress: Boolean = false - set(value) { - field = value - store.dispatchOnMain(OnboardingSaltPayAction.SetClaimRefreshInProgress(value)) - } - -private var handleInProgress: Boolean = false - set(value) { - field = value - store.dispatchOnMain(OnboardingSaltPayAction.SetInProgress(value)) - } - -private suspend fun onError(error: SaltPayActivationError) { - withMainContext { - handleInProgress = false - SaltPayExceptionHandler.handle(error) - } -} - -private suspend fun onException(error: Throwable) { - withMainContext { - handleInProgress = false - SaltPayExceptionHandler.handle(error) - } -} - -private suspend fun checkGasIfNeeded( - saltPayManager: SaltPayActivationManager, - step: SaltPayActivationStep, -): Result { - Timber.d("checkGasIfNeeded: for step: %s", step) - if (step.ordinal >= SaltPayActivationStep.KycIntro.ordinal) { - Timber.d("checkGasIfNeeded: no need to check for step: %s", step) - return Result.Success(Unit) - } - - val result = saltPayManager.checkHasGas() - when (result) { - is Result.Success -> Timber.d("checkGasIfNeeded: has GAS") - is Result.Failure -> Timber.d("checkGasIfNeeded: has NO GAS") - } - return result -} - -@Throws(SaltPayActivationError::class) -private fun assertPinValid(pin: String, pinLength: Int) { - val array = pin.toCharArray() - - if (array.size < pinLength) throw SaltPayActivationError.WeakPin - - val filters: List> = listOf( - AllSymbolsTheSameFilter(), - ) - - if (filters.any { it.filter(pin) }) { - throw SaltPayActivationError.WeakPin - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayReducer.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayReducer.kt deleted file mode 100644 index ad3c493336..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayReducer.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay.redux - -import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState -import org.rekotlin.Action - -/** -[REDACTED_AUTHOR] - */ -object OnboardingSaltPayReducer { - fun reduce(action: Action, state: OnboardingWalletState): OnboardingWalletState { - return internalReduce(action, state) - } -} - -@Suppress("ComplexMethod") -private fun internalReduce(anyAction: Action, onboardingWalletState: OnboardingWalletState): OnboardingWalletState { - val action = anyAction as? OnboardingSaltPayAction ?: return onboardingWalletState - - if (onboardingWalletState.onboardingSaltPayState == null && action is OnboardingSaltPayAction.SetDependencies) { - return onboardingWalletState.copy( - onboardingSaltPayState = OnboardingSaltPayState( - saltPayManager = action.registrationManager, - ), - ) - } - - val oldState = onboardingWalletState.onboardingSaltPayState ?: return onboardingWalletState - - val newState = when (action) { - is OnboardingSaltPayAction.SetAccessCode -> { - oldState.copy( - accessCode = action.accessCode, - ) - } - is OnboardingSaltPayAction.SetPin -> { - oldState.copy(pinCode = action.pin) - } - is OnboardingSaltPayAction.SetStep -> { - if (action.newStep == null) { - oldState - } else { - oldState.copy( - step = action.newStep, - ) - } - } - is OnboardingSaltPayAction.SetAmountToClaim -> { - oldState.copy( - amountToClaim = action.amount, - ) - } - is OnboardingSaltPayAction.SetTokenBalance -> { - oldState.copy( - tokenAmount = oldState.tokenAmount.copy(value = action.balanceValue), - ) - } - is OnboardingSaltPayAction.SetInProgress -> { - oldState.copy( - inProgress = action.isInProgress, - ) - } - is OnboardingSaltPayAction.SetClaimRefreshInProgress -> { - oldState.copy( - claimInProgress = action.isInProgress, - ) - } - else -> oldState - } - - return when (newState) { - oldState -> onboardingWalletState - else -> { - onboardingWalletState.copy(onboardingSaltPayState = newState) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayState.kt deleted file mode 100644 index 7b68518634..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayState.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay.redux - -import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.Blockchain -import com.tangem.domain.common.SaltPayWorkaround -import com.tangem.tap.common.toggleWidget.WidgetState -import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager -import com.tangem.tap.features.wallet.redux.ProgressState -import java.math.BigDecimal - -/** -[REDACTED_AUTHOR] - */ -data class OnboardingSaltPayState( - @Transient - val saltPayManager: SaltPayActivationManager = SaltPayActivationManager.stub(), - val pinCode: String? = null, - val accessCode: String? = null, - val amountToClaim: Amount? = null, - val tokenAmount: Amount = Amount(SaltPayWorkaround.tokenFrom(Blockchain.SaltPay), BigDecimal.ZERO), - val step: SaltPayActivationStep = SaltPayActivationStep.None, - val saltPayCardArtworkUrl: String? = null, - val inProgress: Boolean = false, - val claimInProgress: Boolean = false, -) { - - val mainButtonState: WidgetState - get() = if (inProgress) ProgressState.Loading else ProgressState.Done - - val pinLength: Int = 4 -} - -enum class SaltPayActivationStep { - None, - NoGas, - NeedPin, - CardRegistration, - KycIntro, - KycStart, - KycWaiting, - KycReject, - Claim, - ClaimInProgress, - ClaimSuccess, - Success, -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayStateHandler.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayStateHandler.kt deleted file mode 100644 index b4c5bf2c60..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayStateHandler.kt +++ /dev/null @@ -1,387 +0,0 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay.ui - -import android.net.Uri -import android.view.View -import android.view.ViewGroup -import android.view.animation.OvershootInterpolator -import android.widget.ProgressBar -import androidx.annotation.LayoutRes -import androidx.annotation.StringRes -import androidx.constraintlayout.widget.ConstraintSet -import androidx.core.view.children -import androidx.transition.TransitionManager -import coil.load -import coil.size.Scale -import com.google.android.material.appbar.MaterialToolbar -import com.google.android.material.button.MaterialButton -import com.tangem.common.extensions.guard -import com.tangem.core.analytics.Analytics -import com.tangem.tap.common.analytics.events.Onboarding -import com.tangem.tap.common.compose.PinCodeWidget -import com.tangem.tap.common.extensions.* -import com.tangem.tap.common.feedback.SupportInfo -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.common.redux.navigation.AppScreen -import com.tangem.tap.common.redux.navigation.NavigationAction -import com.tangem.tap.common.toggleWidget.IndeterminateProgressButtonWidget -import com.tangem.tap.common.toggleWidget.RefreshBalanceWidget -import com.tangem.tap.common.transitions.InternalNoteLayoutTransition -import com.tangem.tap.features.onboarding.products.wallet.redux.* -import com.tangem.tap.features.onboarding.products.wallet.saltPay.UtorgWebChromeClient -import com.tangem.tap.features.onboarding.products.wallet.saltPay.UtorgWebViewClient -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.SaltPayActivationStep -import com.tangem.tap.features.onboarding.products.wallet.ui.OnboardingWalletFragment -import com.tangem.tap.features.wallet.redux.ProgressState -import com.tangem.tap.store -import com.tangem.wallet.R -import com.tangem.wallet.databinding.LayoutOnboardingContainerBottomBinding -import com.tangem.wallet.databinding.LayoutOnboardingContainerTopBinding -import com.tangem.wallet.databinding.LayoutOnboardingMainBinding - -/** -[REDACTED_AUTHOR] - */ -internal class OnboardingSaltPayStateHandler( - private val walletFragment: OnboardingWalletFragment, -) { - - private val toolbar: MaterialToolbar by lazy { walletFragment.binding.toolbar } - private val claimBinding: LayoutOnboardingMainBinding by lazy { walletFragment.bindingSaltPay.claim } - private val topContainer: LayoutOnboardingContainerTopBinding by lazy { claimBinding.onboardingTopContainer } - private val actionContainer: LayoutOnboardingContainerBottomBinding by lazy { - claimBinding.onboardingActionContainer - } - - private val btnRefreshBalanceWidget by lazy { - RefreshBalanceWidget(claimBinding.onboardingTopContainer.onboardingWalletContainer) - } - - private var progressButton: SaltPayProgressButton? = null - private var previousStep: SaltPayActivationStep = SaltPayActivationStep.None - - fun newState(state: OnboardingWalletState) { - handleCardArtworks(state) - - when (state.step) { - OnboardingWalletStep.SaltPay -> setSaltPayStep(state.onboardingSaltPayState) - OnboardingWalletStep.Backup -> { - if (state.backupState.backupStep == BackupStep.Finished && !state.backupState.isInterruptedBackup) { - // if backup finished -> switch OnboardingWalletStep to the SaltPay - store.dispatch(OnboardingWalletAction.GetToSaltPayStep) - store.dispatch(OnboardingSaltPayAction.OnSwitchedToSaltPayProcess) - } else { - // if not -> back to the standard backup process - walletFragment.handleOnboardingStep(state) - } - } - else -> walletFragment.handleOnboardingStep(state) - } - } - - private fun handleCardArtworks(state: OnboardingWalletState) = with(walletFragment.binding) { - // TODO: SaltPay: remove hardCode - if (state.onboardingSaltPayState?.saltPayCardArtworkUrl == null) { - imvFrontCard.load(R.drawable.img_salt_pay_visa) { - scale(Scale.FILL) - crossfade(enable = true) - } - } else { - val uri = Uri.parse(state.onboardingSaltPayState.saltPayCardArtworkUrl) - walletFragment.loadImageIntoImageView(uri, imvFrontCard) - } - imvFirstBackupCard.load(R.drawable.card_placeholder_wallet) - - // if (state.onboardingSaltPayState?.saltPayCardArtworkUrl == null) { - // //if saltPay url not loaded -> load from resource - // val bitmap = BitmapFactory.decodeResource(walletFragment.resources, R.drawable.img_salt_pay_visa) - // imvFrontCard.setImageBitmap(bitmap) - // } else { - // walletFragment.loadImageIntoImageView(state.onboardingSaltPayState.saltPayCardArtworkUrl, imvFrontCard) - // } - // walletFragment.loadImageIntoImageView(state.cardArtworkUrl, imvFirstBackupCard) - } - - fun showAddBackupCards(state: BackupState) = with(walletFragment.binding) { - when (state.backupCardsNumber) { - 0 -> { - tvHeader.text = walletFragment.getText(R.string.onboarding_saltpay_title_no_backup_card) - tvBody.text = walletFragment.getText(R.string.onboarding_saltpay_subtitle_no_backup_cards) - } - 1 -> { - tvHeader.text = walletFragment.getText(R.string.onboarding_saltpay_title_one_backup_card) - tvBody.text = walletFragment.getText(R.string.onboarding_saltpay_subtitle_one_backup_card) - } - else -> {} - } - } - - private fun setSaltPayStep(onboardingSaltPayState: OnboardingSaltPayState?) { - val state = onboardingSaltPayState.guard { - store.dispatchDebugErrorNotification("SaltPayView: setSaltPayStep: onboardingSaltPayState = null") - return - } - - walletFragment.binding.onboardingWalletContainer.hide() - walletFragment.bindingSaltPay.onboardingSaltpayContainer.show() - - when (state.step) { - 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.ClaimSuccess -> handleClaim(state) - SaltPayActivationStep.Success -> handleSuccess() - else -> Unit - } - progressButton?.changeState(state.mainButtonState) - } - - private fun handleNoGas() { - // normally this shouldn't happen - store.dispatch(NavigationAction.PopBackTo(AppScreen.Home)) - store.dispatchDialogShow(SaltPayDialog.Activation.NoGas) - } - - private fun handleNeedPin() = with(walletFragment.bindingSaltPay) { - toolbar.title = getText(R.string.onboarding_navbar_pin) - showOnlyView(pinCode.root) { - progressButton = SaltPayProgressButton(pinCode.root) - progressButton?.mainView?.isEnabled = false - - var enteredPinCode = "" - pinCode.flPinCodeContainer.setContent { - PinCodeWidget { code, isLastSymbolEntered -> - enteredPinCode = code - progressButton?.mainView?.isEnabled = isLastSymbolEntered - } - } - pinCode.btnSetPin.setOnClickListener { - store.dispatch(OnboardingSaltPayAction.TrySetPin(enteredPinCode)) - } - } - } - - private fun handleCardRegistration() = with(walletFragment.bindingSaltPay) { - toolbar.title = getText(R.string.onboarding_navbar_register_wallet) - showOnlyView(connectCard.root) { - progressButton = SaltPayProgressButton(connectCard.root) - connectCard.btnConnect.setOnClickListener { - Analytics.send(Onboarding.ButtonConnect()) - store.dispatch(OnboardingSaltPayAction.RegisterCard) - } - } - } - - private fun handleKycIntro() = with(walletFragment.bindingSaltPay) { - toolbar.title = getText(R.string.onboarding_navbar_kyc_start) - showOnlyView(verifyIdentity.root) { - progressButton = SaltPayProgressButton(verifyIdentity.root) - verifyIdentity.btnVerify.setOnClickListener { - store.dispatch(OnboardingSaltPayAction.OpenUtorgKYC) - } - } - } - - private fun handleKycStart(state: OnboardingSaltPayState) = with(walletFragment.bindingSaltPay) { - toolbar.title = getText(R.string.onboarding_navbar_kyc_start) - showOnlyView(webvVerifyIdentity) { - progressButton = null - webvVerifyIdentity.configureSettings() - webvVerifyIdentity.webViewClient = UtorgWebViewClient( - successUrl = state.saltPayManager.kycUrlProvider.doneUrl, - onSuccess = { - webvVerifyIdentity.stop() - store.dispatch(OnboardingSaltPayAction.UtorgKYCRedirectSuccess) - }, - ) - webvVerifyIdentity.webChromeClient = UtorgWebChromeClient(walletFragment.requireActivity()) - webvVerifyIdentity.loadUrl(state.saltPayManager.kycUrlProvider.requestUrl) - } - } - - private fun handleKycWaiting() = with(walletFragment.bindingSaltPay.kycInProgress) { - toolbar.title = getText(R.string.onboarding_navbar_kyc_progress) - showOnlyView(root) - - imvInProgress.setDrawable(R.drawable.ic_in_progress) - tvHeader.text = getText(R.string.onboarding_title_kyc_waiting) - tvBody.text = getText(R.string.onboarding_subtitle_kyc_waiting) - - btnOpenSupportChat.hide() - btnOpenSupportChat.setOnClickListener { - store.dispatch(GlobalAction.OpenChat(SupportInfo())) - } - - btnKycAction.text = getText(R.string.onboarding_button_kyc_waiting) - btnKycAction.setOnClickListener { - store.dispatch(OnboardingSaltPayAction.Update()) - } - progressButton = SaltPayProgressButton(root) - } - - private fun handleKycReject() = with(walletFragment.bindingSaltPay.kycInProgress) { - toolbar.title = getText(R.string.onboarding_navbar_kyc_progress) - showOnlyView(root) - - imvInProgress.setDrawable(R.drawable.ic_reject) - tvHeader.text = getText(R.string.onboarding_title_kyc_retry) - tvBody.text = getText(R.string.onboarding_subtitle_kyc_retry) - - btnOpenSupportChat.hide() - btnKycAction.text = getText(R.string.onboarding_button_kyc_start) - btnKycAction.setOnClickListener { - store.dispatch(OnboardingSaltPayAction.Update()) - } - progressButton = SaltPayProgressButton(root) - } - - @Suppress("LongMethod") - private fun handleClaim(state: OnboardingSaltPayState) = with(walletFragment.bindingSaltPay) { - toolbar.title = getText(R.string.onboarding_getting_started) - val btnMain = actionContainer.btnContainer.findViewById(R.id.btn_main_action) - val tvHeader = actionContainer.tvHeader - val tvBody = actionContainer.tvBody - - showOnlyView(claimBinding.root) { - // topContainer.progress.pbState.hide() - progressButton = SaltPayProgressButton(actionContainer.root) - topContainer.imvCardBackground.apply { - setBackgroundDrawable(context.getDrawableCompat(R.drawable.shape_rectangle_rounded_8)) - } - topContainer.imvFrontCard.load(R.drawable.img_salt_pay_visa) { - scale(Scale.FILL) - crossfade(enable = true) - } - actionContainer.btnAlternativeAction.hide() - updateConstraints(state.step, R.layout.lp_onboarding_topup_wallet) - } - - btnRefreshBalanceWidget.changeState(if (state.claimInProgress) ProgressState.Loading else ProgressState.Done) - if (btnRefreshBalanceWidget.isShowing != true) { - btnRefreshBalanceWidget.mainView.setOnClickListener { - store.dispatch(OnboardingSaltPayAction.RefreshClaim) - } - } - val tokenAmountString = tokenAmountString(state) - topContainer.onboardingTvBalance.tvBalanceValue.text = tokenAmountString ?: "" - topContainer.onboardingTvBalance.tvBalanceCurrency.text = "" - - when (state.step) { - SaltPayActivationStep.Claim -> { - claimValueString(state)?.let { - tvHeader.text = getText(R.string.onboarding_title_claim, it) - } - tvBody.text = getText(R.string.onboarding_subtitle_claim) - - btnMain.text = getText(R.string.onboarding_button_claim) - btnMain.isEnabled - btnMain.setOnClickListener { - Analytics.send(Onboarding.ButtonClaim()) - store.dispatch(OnboardingSaltPayAction.Claim) - } - progressButton = SaltPayProgressButton(actionContainer.root) - progressButton?.isEnabled = true - } - SaltPayActivationStep.ClaimInProgress -> { - tvHeader.text = getText(R.string.onboarding_title_claim_progress) - tvBody.text = getText(R.string.onboarding_subtitle_claim_progress) - btnMain.text = getText(R.string.onboarding_button_claim) - progressButton = SaltPayProgressButton(actionContainer.root) - progressButton?.isEnabled = false - } - SaltPayActivationStep.ClaimSuccess -> { - tvHeader.setText(R.string.common_success) - tvBody.setText(R.string.onboarding_subtitle_success_claim) - - btnMain.setText(R.string.onboarding_button_continue_wallet) - btnMain.setOnClickListener { - walletFragment.showConfetti(false) - store.dispatch(OnboardingWalletAction.FinishOnboarding) - } - - btnRefreshBalanceWidget.mainView.setOnClickListener(null) - updateConstraints(state.step, R.layout.lp_onboarding_done_activation) - walletFragment.showConfetti(true) - progressButton = SaltPayProgressButton(actionContainer.root) - progressButton?.isEnabled = true - } - else -> {} - } - } - - private fun handleSuccess() = with(walletFragment.binding) { - walletFragment.bindingSaltPay.onboardingSaltpayContainer.hide() - onboardingWalletContainer.show() - walletFragment.showSuccess() - tvBody.text = getText(R.string.onboarding_subtitle_success_claim) - layoutButtonsCommon.btnWalletMainAction.text = getText(R.string.onboarding_button_continue_wallet) - } - - private fun tokenAmountString(state: OnboardingSaltPayState): String? { - return state.tokenAmount.value?.toFormattedCurrencyString( - decimals = state.tokenAmount.decimals, - currency = state.tokenAmount.currencySymbol, - ) - } - - private fun claimValueString(state: OnboardingSaltPayState): String? { - return state.amountToClaim?.value?.toFormattedCurrencyString( - decimals = state.amountToClaim.decimals, - currency = state.amountToClaim.currencySymbol, - ) - } - - private fun updateConstraints(currentStep: SaltPayActivationStep, @LayoutRes layoutId: Int) { - if (this.previousStep == currentStep) return - - with(claimBinding.onboardingTopContainer) { - val constraintSet = ConstraintSet() - constraintSet.clone(root.context, layoutId) - constraintSet.applyTo(onboardingWalletContainer) - val transition = InternalNoteLayoutTransition() - transition.interpolator = OvershootInterpolator() - TransitionManager.beginDelayedTransition(onboardingWalletContainer, transition) - } - } - - private fun showOnlyView(view: View, onShowListener: (() -> Unit)? = null) { - walletFragment.bindingSaltPay.onboardingSaltpayContainer.children - .filter { it.id != view.id } - .forEach { it.hide() } - view.show { onShowListener?.invoke() } - } - - private fun getText(@StringRes resId: Int): String { - return walletFragment.getString(resId) - } - - private fun getText(@StringRes resId: Int, vararg formatArgs: Any?): String { - return walletFragment.getString(resId, *formatArgs) - } - - private class SaltPayProgressButton( - root: ViewGroup, - ) : IndeterminateProgressButtonWidget(findButton(root), findProgress(root)) { - companion object { - fun findButton(view: ViewGroup): MaterialButton { - return findContainer(view).children.firstOrNull { it is MaterialButton } as MaterialButton - } - - fun findProgress(view: ViewGroup): View { - return findContainer(view).children.firstOrNull { it is ProgressBar }!! - } - - fun findContainer(view: ViewGroup): ViewGroup { - return view.children.first { it.id == R.id.btn_container } as ViewGroup - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index 13c2a3842e..269449599e 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -37,14 +37,11 @@ import com.tangem.tap.features.FragmentOnBackPressedHandler import com.tangem.tap.features.addBackPressHandler import com.tangem.tap.features.onboarding.OnboardingMenuProvider import com.tangem.tap.features.onboarding.products.wallet.redux.* -import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction -import com.tangem.tap.features.onboarding.products.wallet.saltPay.ui.OnboardingSaltPayStateHandler import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AccessCodeDialog import com.tangem.tap.mainScope import com.tangem.tap.store import com.tangem.wallet.R import com.tangem.wallet.databinding.FragmentOnboardingWalletBinding -import com.tangem.wallet.databinding.LayoutOnboardingSaltpayBinding import com.tangem.wallet.databinding.LayoutOnboardingSeedPhraseBinding import com.tangem.wallet.databinding.ViewOnboardingProgressBinding import dagger.hilt.android.AndroidEntryPoint @@ -62,13 +59,10 @@ class OnboardingWalletFragment : internal val pbBinding: ViewOnboardingProgressBinding by viewBinding(ViewOnboardingProgressBinding::bind) internal val bindingSeedPhrase: LayoutOnboardingSeedPhraseBinding by lazy { binding.onboardingSeedPhraseContainer } - internal val bindingSaltPay: LayoutOnboardingSaltpayBinding by lazy { binding.onboardingSaltpayContainer } private val seedPhraseStateHandler: OnboardingSeedPhraseStateHandler = OnboardingSeedPhraseStateHandler() private val seedPhraseViewModel by viewModels() - private val saltPayStateHandler: OnboardingSaltPayStateHandler = OnboardingSaltPayStateHandler(this) - private lateinit var cardsWidget: WalletCardsWidget private var accessCodeDialog: AccessCodeDialog? = null @@ -108,7 +102,6 @@ class OnboardingWalletFragment : store.dispatch(OnboardingWallet2Action.Init(seedPhraseViewModel.maxProgress)) store.dispatch(OnboardingWalletAction.Init) - store.dispatch(OnboardingSaltPayAction.Init) store.dispatch( OnboardingWalletAction.LoadArtwork( cardArtworkUriForUnfinishedBackup = requireContext().resourceUri(R.drawable.card_placeholder_wallet), @@ -170,7 +163,6 @@ class OnboardingWalletFragment : override fun newState(state: OnboardingWalletState) { if (activity == null || view == null) return - if (state.isSaltPay) reInitCardsWidgetIfNeeded(1) animator.updateBackupState(state.backupState) requireActivity().invalidateOptionsMenu() @@ -182,9 +174,6 @@ class OnboardingWalletFragment : state.wallet2State != null -> { seedPhraseStateHandler.newState(this, state, seedPhraseViewModel) } - state.isSaltPay -> { - saltPayStateHandler.newState(state) - } else -> { loadImageIntoImageView(state.cardArtworkUri, binding.imvFrontCard) loadImageIntoImageView(state.cardArtworkUri, binding.imvFirstBackupCard) @@ -207,7 +196,6 @@ class OnboardingWalletFragment : OnboardingWalletStep.CreateWallet -> setupCreateWalletState() OnboardingWalletStep.Backup -> setBackupState( state = state.backupState, - isSaltPay = state.isSaltPay, isWallet2 = state.wallet2State != null, ) @@ -231,21 +219,21 @@ class OnboardingWalletFragment : animator.setupCreateWalletState() } - private fun setBackupState(state: BackupState, isSaltPay: Boolean, isWallet2: Boolean) { + private fun setBackupState(state: BackupState, isWallet2: Boolean) { when (state.backupStep) { - BackupStep.InitBackup -> showBackupIntro(state, isSaltPay, isWallet2) + BackupStep.InitBackup -> showBackupIntro(state, isWallet2) BackupStep.ScanOriginCard -> showScanOriginCard() - BackupStep.AddBackupCards -> showAddBackupCards(state, isSaltPay) + BackupStep.AddBackupCards -> showAddBackupCards(state) BackupStep.SetAccessCode -> showSetAccessCode() BackupStep.EnterAccessCode -> showEnterAccessCode(state) BackupStep.ReenterAccessCode -> showReenterAccessCode(state) - is BackupStep.WritePrimaryCard -> showWritePrimaryCard(state, isSaltPay) - is BackupStep.WriteBackupCard -> showWriteBackupCard(state, isSaltPay) + is BackupStep.WritePrimaryCard -> showWritePrimaryCard(state) + is BackupStep.WriteBackupCard -> showWriteBackupCard(state) BackupStep.Finished -> showSuccess() } } - private fun showBackupIntro(state: BackupState, isSaltPay: Boolean, isWallet2: Boolean) = with(binding) { + private fun showBackupIntro(state: BackupState, isWallet2: Boolean) = with(binding) { imvFirstBackupCard.show() imvSecondBackupCard.show() @@ -260,7 +248,7 @@ class OnboardingWalletFragment : btnWalletAlternativeAction.text = getText(R.string.onboarding_button_skip_backup) btnWalletAlternativeAction.setOnClickListener { store.dispatch(BackupAction.SkipBackup) } - btnWalletAlternativeAction.show(state.canSkipBackup && !isSaltPay && !isWallet2) + btnWalletAlternativeAction.show(state.canSkipBackup && !isWallet2) } animator.showBackupIntro(state) } @@ -281,7 +269,7 @@ class OnboardingWalletFragment : animator.showScanOriginCard() } - private fun showAddBackupCards(state: BackupState, isSaltPay: Boolean) = with(binding) { + private fun showAddBackupCards(state: BackupState) = with(binding) { prepareBackupView() accessCodeDialog?.dismiss() @@ -299,25 +287,20 @@ class OnboardingWalletFragment : layoutButtonsAddCards.btnContinue.text = getText(R.string.onboarding_button_finalize_backup) layoutButtonsAddCards.btnContinue.setOnClickListener { store.dispatch(BackupAction.FinishAddingBackupCards) } layoutButtonsAddCards.btnContinue.isEnabled = state.backupCardsNumber != 0 - - if (isSaltPay) { - saltPayStateHandler.showAddBackupCards(state) - } else { - when (state.backupCardsNumber) { - 0 -> { - tvHeader.text = getText(R.string.onboarding_title_no_backup_cards) - tvBody.text = getText(R.string.onboarding_subtitle_no_backup_cards) - } - 1 -> { - tvHeader.text = getText(R.string.onboarding_title_one_backup_card) - tvBody.text = getText(R.string.onboarding_subtitle_one_backup_card) - } - 2 -> { - tvHeader.text = getText(R.string.onboarding_title_two_backup_cards) - tvBody.text = getText(R.string.onboarding_subtitle_two_backup_cards) - } - else -> {} + when (state.backupCardsNumber) { + 0 -> { + tvHeader.text = getText(R.string.onboarding_title_no_backup_cards) + tvBody.text = getText(R.string.onboarding_subtitle_no_backup_cards) } + 1 -> { + tvHeader.text = getText(R.string.onboarding_title_one_backup_card) + tvBody.text = getText(R.string.onboarding_subtitle_one_backup_card) + } + 2 -> { + tvHeader.text = getText(R.string.onboarding_title_two_backup_cards) + tvBody.text = getText(R.string.onboarding_subtitle_two_backup_cards) + } + else -> {} } animator.showAddBackupCards(state, state.backupCardsNumber) @@ -363,25 +346,19 @@ class OnboardingWalletFragment : accessCodeDialog?.showError(state.accessCodeError) } - private fun showWritePrimaryCard(state: BackupState, isSaltPay: Boolean) = with(binding) { + private fun showWritePrimaryCard(state: BackupState) = with(binding) { accessCodeDialog?.dismiss() reInitCardsWidgetIfNeeded(state.backupCardsNumber) prepareViewForFinalizeStep() val cardIdFormatter = CardIdFormatter(CardIdDisplayFormat.LastMasked(4)) - if (isSaltPay) { - tvHeader.text = getText(R.string.onboarding_saltpay_title_prepare_origin) - tvBody.text = getString(R.string.onboarding_twins_interrupt_warning) - layoutButtonsCommon.btnWalletMainAction.text = getText(R.string.onboarding_saltpay_button_backup_origin) - } else { - tvHeader.text = getText(R.string.common_origin_card) - tvBody.text = getString( - R.string.onboarding_subtitle_scan_primary_card_format, - state.primaryCardId?.let { cardIdFormatter.getFormattedCardId(it) }, - ) - layoutButtonsCommon.btnWalletMainAction.text = getText(R.string.onboarding_button_backup_origin) - } + tvHeader.text = getText(R.string.common_origin_card) + tvBody.text = getString( + R.string.onboarding_subtitle_scan_primary_card_format, + state.primaryCardId?.let { cardIdFormatter.getFormattedCardId(it) }, + ) + layoutButtonsCommon.btnWalletMainAction.text = getText(R.string.onboarding_button_backup_origin) layoutButtonsCommon.btnWalletMainAction.setOnClickListener { store.dispatch(BackupAction.WritePrimaryCard) } animator.showWritePrimaryCard(state) @@ -399,27 +376,21 @@ class OnboardingWalletFragment : imvSecondBackupCard.show() } - private fun showWriteBackupCard(state: BackupState, isSaltPay: Boolean) = with(binding) { + private fun showWriteBackupCard(state: BackupState) = with(binding) { prepareViewForFinalizeStep() reInitCardsWidgetIfNeeded(state.backupCardsNumber) val cardNumber = (state.backupStep as? BackupStep.WriteBackupCard)?.cardNumber ?: 1 - if (isSaltPay) { - tvHeader.text = getString(R.string.onboarding_saltpay_title_backup_card) - tvBody.text = getString(R.string.onboarding_twins_interrupt_warning) - layoutButtonsCommon.btnWalletMainAction.text = getString(R.string.onboarding_saltpay_title_backup_card) - } else { - val cardIdFormatter = CardIdFormatter(CardIdDisplayFormat.LastMasked(4)) - tvHeader.text = getString(R.string.onboarding_title_backup_card_format, cardNumber) - tvBody.text = getString( - R.string.onboarding_subtitle_scan_backup_card_format, - cardIdFormatter.getFormattedCardId(state.backupCardIds[cardNumber - 1]), - ) - layoutButtonsCommon.btnWalletMainAction.text = getString( - R.string.onboarding_button_backup_card_format, - cardNumber, - ) - } + val cardIdFormatter = CardIdFormatter(CardIdDisplayFormat.LastMasked(4)) + tvHeader.text = getString(R.string.onboarding_title_backup_card_format, cardNumber) + tvBody.text = getString( + R.string.onboarding_subtitle_scan_backup_card_format, + cardIdFormatter.getFormattedCardId(state.backupCardIds[cardNumber - 1]), + ) + layoutButtonsCommon.btnWalletMainAction.text = getString( + R.string.onboarding_button_backup_card_format, + cardNumber, + ) layoutButtonsCommon.btnWalletMainAction.setOnClickListener { store.dispatch(BackupAction.WriteBackupCard(cardNumber)) } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/InterruptOnboardingDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/InterruptOnboardingDialog.kt similarity index 92% rename from app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/InterruptOnboardingDialog.kt rename to app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/InterruptOnboardingDialog.kt index 36827b96a4..678c2ca2df 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/InterruptOnboardingDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/InterruptOnboardingDialog.kt @@ -1,4 +1,4 @@ -package com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog +package com.tangem.tap.features.onboarding.products.wallet.ui.dialogs import android.app.Dialog import android.content.Context diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 1dde548a55..9c1feed6b4 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -132,6 +132,5 @@ data class Artwork( const val MARTA_CARD_ID = "BC02" const val TWIN_CARD_1 = "https://app.tangem.com/cards/card_tg085.png" const val TWIN_CARD_2 = "https://app.tangem.com/cards/card_tg086.png" - const val SALT_PAY_URL = "key_for_switch_url_to_drawableId_of_salt_pay_card" } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index b15b018e09..47d07b91b0 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -24,7 +24,6 @@ import com.tangem.core.analytics.Analytics import com.tangem.core.ui.fragments.setStatusBarColor import com.tangem.core.ui.utils.OneTouchClickListener import com.tangem.datasource.connection.NetworkConnectionManager -import com.tangem.domain.common.util.cardTypesResolver import com.tangem.feature.swap.api.SwapFeatureToggleManager import com.tangem.feature.swap.domain.SwapInteractor import com.tangem.tap.MainActivity @@ -47,7 +46,6 @@ import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter import com.tangem.tap.features.wallet.ui.wallet.MultiWalletView import com.tangem.tap.features.wallet.ui.wallet.SingleWalletView import com.tangem.tap.features.wallet.ui.wallet.WalletView -import com.tangem.tap.features.wallet.ui.wallet.saltPay.SaltPayWalletView import com.tangem.tap.store import com.tangem.wallet.BuildConfig import com.tangem.wallet.R @@ -166,20 +164,13 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), SafeStoreSubscriber { - walletView.onViewDestroy() - walletView = SaltPayWalletView() - walletView.changeWalletView(this, binding) - } state.isMultiwalletAllowed && walletView !is MultiWalletView -> { walletView.onViewDestroy() walletView = MultiWalletView() walletView.changeWalletView(this, binding) } - !state.isMultiwalletAllowed && !isSaltPay && walletView !is SingleWalletView -> { + !state.isMultiwalletAllowed && walletView !is SingleWalletView -> { walletView.onViewDestroy() walletView = SingleWalletView() walletView.changeWalletView(this, binding) @@ -199,9 +190,9 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), SafeStoreSubscriber ViewGroup = { - val inflater = LayoutInflater.from(it.context) - ItemSaltPayTxHistoryShimmerBinding.inflate(inflater, it, false).root - } - val adapter = ShimmerRecyclerAdapter(vhViewFactory) - rvTxHistoryShimmer.adapter = adapter - rvTxHistoryShimmer.addItemDecoration(itemDecorator) - adapter.submitList( - listOf( - ShimmerData(), - ShimmerData(), - ShimmerData(), - ), - ) - - rvTxHistory.adapter = TxHistoryAdapter() - rvTxHistory.addItemDecoration(itemDecorator) - } - - override fun onNewState(state: WalletState) { - val balanceWidget = balanceWidget ?: return - val txWidget = txWidget ?: return - - val exchangeManager = store.state.globalState.exchangeManager - setupBalanceWidget(balanceWidget, exchangeManager, state) - setupTxHistoryWidget(txWidget, state) - } - - private fun setupBalanceWidget( - balanceWidget: LayoutSaltPayBalanceBinding, - exchangeManager: CurrencyExchangeManager, - state: WalletState, - ) = with(balanceWidget) { - Timber.d("setupBalanceWidget") - val tokenData = state.primaryTokenData ?: return - - val appCurrency = store.state.globalState.appCurrency - val mainProgressState = state.state - - if (mainProgressState == ProgressState.Loading) { - veilBalance.veil() - veilBalanceCrypto.veil() - } else { - veilBalanceCrypto.unVeil() - } - - tvUnreachable.animateVisibility(show = mainProgressState == ProgressState.Error) - veilBalanceCrypto.animateVisibility(show = mainProgressState != ProgressState.Error) - - if (tokenData.fiatRate == null) { - veilBalance.veil() - } else { - veilBalance.unVeil() - tvBalance.text = tokenData.getFormattedFiatAmount(appCurrency) - } - - tvBalanceCrypto.text = tokenData.getFormattedAmount() - - tvCurrencyName.text = appCurrency.code - tvCurrencyName.setOnClickListener { - store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency) - } - - btnBuy.show(tokenData.isAvailableToBuy(exchangeManager)) - btnBuy.setOnClickListener { - Analytics.send(MainScreen.ButtonBuy()) - store.dispatch(WalletAction.TradeCryptoAction.Buy(false)) - } - } - - private fun setupTxHistoryWidget(txWidget: LayoutSaltPayTxHistoryBinding, state: WalletState) { - Timber.d("setupTxHistoryWidget") - if (state.state == ProgressState.Loading) { - handleTxLoading(txWidget) - return - } - if (state.state == ProgressState.Error) { - handleTxError(txWidget) - return - } - if (state.state != ProgressState.Done) return - val walletAddress = state.primaryWalletManager?.wallet?.address ?: return - val tokenData = state.primaryTokenData ?: return - val historyTransactions = tokenData.historyTransactions ?: return - if (historyTransactions.isEmpty()) { - handleTxEmpty(txWidget) - return - } - - scope.launch { - val dateAssociatedHistory = mutableListOf>>() - historyTransactions.forEach { tx -> - val txHistoryData = HistoryTransactionData(tx, walletAddress) - val item = dateAssociatedHistory.firstOrNull { it.first == txHistoryData.date } - if (item == null) { - dateAssociatedHistory.add(Pair(txHistoryData.date, mutableListOf(txHistoryData))) - } else { - item.second.add(txHistoryData) - } - } - - val rvDataList = mutableListOf() - dateAssociatedHistory.forEach { (txData, txHistoryData) -> - rvDataList.add(HistoryItemData.Date(txData)) - rvDataList.addAll(txHistoryData.map { HistoryItemData.TransactionData(it) }) - } - - withMainContext { handleTxSuccess(txWidget, rvDataList) } - } - } - - private fun handleTxLoading(txWidget: LayoutSaltPayTxHistoryBinding) = with(txWidget) { - Timber.d("handleTxLoading") - groupEmpty.hide() - groupError.hide() - groupSuccess.hide() - // root.beginDelayedTransition() - groupShimmer.show() - } - - private fun handleTxSuccess(txWidget: LayoutSaltPayTxHistoryBinding, dataList: List) = - with(txWidget) { - Timber.d("handleTxSuccess") - groupShimmer.hide() - groupEmpty.hide() - groupError.hide() - // root.beginDelayedTransition() - updateTxHistoryWidget(txWidget, dataList) - groupSuccess.show() - } - - private fun handleTxEmpty(txWidget: LayoutSaltPayTxHistoryBinding) = with(txWidget) { - Timber.d("handleTxEmpty") - groupShimmer.hide() - groupError.hide() - groupSuccess.hide() - // root.beginDelayedTransition() - updateTxHistoryWidget(txWidget, emptyList()) - groupEmpty.show() - } - - private fun handleTxError(txWidget: LayoutSaltPayTxHistoryBinding) = with(txWidget) { - Timber.d("handleTxError") - groupShimmer.hide() - groupEmpty.hide() - groupSuccess.hide() - // root.beginDelayedTransition() - updateTxHistoryWidget(txWidget, emptyList()) - groupError.show() - } - - private fun updateTxHistoryWidget(txWidget: LayoutSaltPayTxHistoryBinding, dataList: List) = - with(txWidget) { - (rvTxHistory.adapter as TxHistoryAdapter).submitList(dataList) - } - - override fun onViewDestroy() { - Timber.d("onViewDestroy") - txWidget?.apply { - rvTxHistoryShimmer.removeItemDecoration(itemDecorator) - rvTxHistory.removeItemDecoration(itemDecorator) - } - super.onViewDestroy() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/HistoryItemData.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/HistoryItemData.kt deleted file mode 100644 index 7f194e047e..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/HistoryItemData.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.tangem.tap.features.wallet.ui.wallet.saltPay.rv - -import com.tangem.blockchain.common.TransactionData -import com.tangem.blockchain.common.TransactionStatus -import com.tangem.common.extensions.guard -import com.tangem.tap.common.extensions.toFormattedCurrencyString -import com.tangem.tap.features.wallet.models.PendingTransactionType -import java.text.SimpleDateFormat -import java.util.* - -/** -[REDACTED_AUTHOR] - */ -sealed class HistoryItemData( - val viewType: Int, - val itemId: Long, -) { - data class Date(val date: String) : HistoryItemData(0, date.hashCode().toLong()) - data class TransactionData(val data: HistoryTransactionData) : HistoryItemData(1, data.address.hashCode().toLong()) -} - -data class HistoryTransactionData( - private val transactionData: TransactionData, - private val walletAddress: String, -) { - - val isInProgress: Boolean = transactionData.status == TransactionStatus.Unconfirmed - - val transactionType: PendingTransactionType = when { - transactionData.sourceAddress.lowercase() == walletAddress.lowercase() -> PendingTransactionType.Outgoing - transactionData.destinationAddress.lowercase() == walletAddress.lowercase() -> PendingTransactionType.Incoming - else -> PendingTransactionType.Unknown - } - - val address: String = when (transactionType) { - PendingTransactionType.Incoming -> transactionData.sourceAddress.reduceAddress() - PendingTransactionType.Outgoing -> transactionData.destinationAddress.reduceAddress() - PendingTransactionType.Unknown -> "Unknown address" - } - - val time: String = transactionData.date?.let { - SimpleDateFormat("HH:mm").format(it.time) - } ?: "00:00" - - val date: String = calculateDate() - - val txSign: String = when (transactionType) { - PendingTransactionType.Incoming -> "+" - PendingTransactionType.Outgoing -> "-" - PendingTransactionType.Unknown -> "" - } - - val amountValue: String = transactionData.amount.value - ?.toFormattedCurrencyString(8, transactionData.amount.currencySymbol) ?: "0" - - private fun calculateDate(): String { - val calendarTx = transactionData.date.guard { return "Unknown" } - - val calendarNow = Calendar.getInstance() - val oldDateFormatter = SimpleDateFormat("dd.MM.yyyy") - - val date = if (calendarTx.get(Calendar.YEAR) == calendarNow.get(Calendar.YEAR)) { - val dayOfYearTx = calendarTx.get(Calendar.DAY_OF_YEAR) - val dayOfYearNow = calendarNow.get(Calendar.DAY_OF_YEAR) - when { - dayOfYearNow == dayOfYearTx -> "Today" - dayOfYearNow - dayOfYearTx == 1 -> "Tomorrow" - else -> oldDateFormatter.format(calendarTx.time) - } - } else { - oldDateFormatter.format(calendarTx.time) - } - - return date - } - - @Suppress("MagicNumber") - private fun String.reduceAddress(): String = "${substring(0..5)}...${substring(length - 4)}" -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/TxHistoryAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/TxHistoryAdapter.kt deleted file mode 100644 index 0363cffefe..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/TxHistoryAdapter.kt +++ /dev/null @@ -1,113 +0,0 @@ -package com.tangem.tap.features.wallet.ui.wallet.saltPay.rv - -import android.graphics.PorterDuff -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ListAdapter -import androidx.recyclerview.widget.RecyclerView -import com.tangem.tap.common.extensions.getColor -import com.tangem.tap.common.extensions.setDrawable -import com.tangem.tap.common.extensions.show -import com.tangem.tap.features.wallet.models.PendingTransactionType -import com.tangem.wallet.R -import com.tangem.wallet.databinding.ItemSaltPayTxHistoryBinding -import com.tangem.wallet.databinding.ItemSaltPayTxHistoryDateBinding - -/** -[REDACTED_AUTHOR] - */ -internal class TxHistoryAdapter : ListAdapter(DiffUtilCallback) { - - override fun getItemId(position: Int): Long = if (currentList.isEmpty()) { - 0L - } else { - currentList[position].itemId - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseTxHistoryVH { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - 0 -> { - val layout = ItemSaltPayTxHistoryDateBinding.inflate(inflater, parent, false) - DateItemVH(layout) - } - 1 -> { - val layout = ItemSaltPayTxHistoryBinding.inflate(inflater, parent, false) - TransactionItemVH(layout) - } - else -> throw UnsupportedOperationException() - } - } - - override fun getItemViewType(position: Int): Int = currentList[position].viewType - - override fun onBindViewHolder(holder: BaseTxHistoryVH, position: Int) { - holder.bind(currentList[position]) - } - - private object DiffUtilCallback : DiffUtil.ItemCallback() { - override fun areContentsTheSame(oldItem: HistoryItemData, newItem: HistoryItemData) = oldItem == newItem - override fun areItemsTheSame(oldItem: HistoryItemData, newItem: HistoryItemData) = oldItem == newItem - } -} - -internal abstract class BaseTxHistoryVH(layout: View) : RecyclerView.ViewHolder(layout) { - abstract fun bind(data: HistoryItemData) -} - -private class DateItemVH( - private val binding: ItemSaltPayTxHistoryDateBinding, -) : BaseTxHistoryVH(binding.root) { - - override fun bind(data: HistoryItemData) = with(binding) { - val vhData = (data as? HistoryItemData.Date)?.date ?: return - - tvTitleDate.text = vhData - } -} - -private class TransactionItemVH( - private val binding: ItemSaltPayTxHistoryBinding, -) : BaseTxHistoryVH(binding.root) { - - override fun bind(data: HistoryItemData) { - val vhData = (data as? HistoryItemData.TransactionData)?.data ?: return - setupImage(vhData) - setupTitle(vhData) - setupSubtitle(vhData) - setupBalance(vhData) - } - - private fun setupImage(data: HistoryTransactionData) = with(binding) { - val drawable = when (data.transactionType) { - PendingTransactionType.Incoming -> R.drawable.ic_tx_incoming - PendingTransactionType.Outgoing -> R.drawable.ic_tx_outgoing - PendingTransactionType.Unknown -> null - } - drawable?.let { imvTx.setDrawable(it) } - - if (data.isInProgress) { - imvTx.setColorFilter(imvTx.getColor(R.color.icon_attention), PorterDuff.Mode.SRC_ATOP) - } else { - imvTx.clearColorFilter() - } - } - - private fun setupTitle(data: HistoryTransactionData) = with(binding) { - tvTxHash.text = data.address - } - - private fun setupSubtitle(data: HistoryTransactionData) = with(binding) { - tvTxStatus.show(data.isInProgress) - tvTxTime.show(!data.isInProgress) - tvTxTime.text = data.time - } - - private fun setupBalance(data: HistoryTransactionData) = with(binding) { - tvTxAmountSign.text = data.txSign - tvTxAmountValue.text = data.amountValue - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt index 077c90ca2c..f1c972ae02 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt @@ -22,7 +22,6 @@ import com.tangem.tap.domain.model.builders.UserWalletBuilder import com.tangem.tap.domain.model.builders.UserWalletIdBuilder import com.tangem.tap.domain.scanCard.ScanCardProcessor import com.tangem.tap.domain.userWalletList.unlockIfLockable -import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.firstOrNull @@ -156,16 +155,8 @@ internal class WalletSelectorMiddleware { onFailure = { error -> // Rollback policy if card scanning was failed tangemSdkManager.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode) - when { - error is TangemSdkError.ExceptionError && error.cause is SaltPayActivationError -> { - store.dispatchOnMain(WalletSelectorAction.AddWallet.Success) - store.dispatchOnMain(NavigationAction.PopBackTo()) - } - else -> { - Timber.e(error, "Unable to scan card") - store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error)) - } - } + Timber.e(error, "Unable to scan card") + store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error)) }, ) } diff --git a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt index a7dc158068..9f7143077a 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt @@ -20,7 +20,6 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.model.builders.UserWalletBuilder import com.tangem.tap.domain.scanCard.ScanCardProcessor import com.tangem.tap.domain.userWalletList.unlockIfLockable -import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError import com.tangem.tap.features.signin.redux.SignInAction import kotlinx.coroutines.launch import org.rekotlin.Middleware @@ -133,8 +132,8 @@ internal class WelcomeMiddleware { scope.launch { onCardScanned(scanResponse) } }, onFailure = { - when { - it is TangemSdkError.ExceptionError && it.cause is SaltPayActivationError -> { + when (it) { + is TangemSdkError.ExceptionError -> { store.dispatchOnMain(WelcomeAction.ProceedWithCard.Success) } else -> { diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/BuyExchangeService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/BuyExchangeService.kt index 180f96317b..07804272ed 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/BuyExchangeService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/BuyExchangeService.kt @@ -1,36 +1,26 @@ package com.tangem.tap.network.exchangeServices import com.tangem.blockchain.common.Blockchain -import com.tangem.domain.models.scan.ProductType import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoService -import com.tangem.tap.network.exchangeServices.utorg.UtorgExchangeService import com.tangem.tap.scope import kotlinx.coroutines.launch /** [REDACTED_AUTHOR] * Temporary wrapper for the buy services. Service switches based on selected product type. - * Just now - UtorgService used only for the SaltPay cards */ internal class BuyExchangeService( - private val productTypeProvider: () -> ProductType?, private val mercuryoService: MercuryoService, - private val utorgService: UtorgExchangeService, ) : ExchangeService, ExchangeUrlBuilder { init { scope.launch { mercuryoService.update() - utorgService.update() } } - private val currentService: ExchangeService - get() = when (productTypeProvider.invoke()) { - ProductType.SaltPay -> utorgService - else -> mercuryoService - } + private val currentService: ExchangeService = mercuryoService override suspend fun update() { currentService.update() diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/UtorgEnvironment.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/UtorgEnvironment.kt deleted file mode 100644 index 0aac5a8b43..0000000000 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/UtorgEnvironment.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.tangem.tap.network.exchangeServices.utorg - -import android.net.Uri -import com.tangem.datasource.api.common.createRetrofitInstance -import com.tangem.tap.network.exchangeServices.utorg.api.UtorgApi -import com.tangem.tap.network.exchangeServices.utorg.mock.MockUtorgApi -import okhttp3.Interceptor -import okhttp3.Response -import java.util.* - -/** -[REDACTED_AUTHOR] - */ -data class UtorgEnvironment( - val baseUri: Uri, - val sidValue: String, - val apiVersion: String, - val utorgApi: UtorgApi, - val successUrl: String = "https://success.tangem.com", -) { - companion object { - private val PROD_BASE_URL = Uri.parse("https://app.utorg.pro") - private const val PROD_VERSION = "v1" - - private val STAGE_BASE_URL = Uri.parse("https://app-stage.utorg.pro") - private const val STAGE_VERSION = "v1" - - fun prod(authProvider: UtorgAuthProvider, apiVersion: String = PROD_VERSION): UtorgEnvironment = - UtorgEnvironment( - baseUri = PROD_BASE_URL, - sidValue = authProvider.sidValue, - apiVersion = apiVersion, - utorgApi = createApi(PROD_BASE_URL, authProvider, false), - ) - - fun stage( - authProvider: UtorgAuthProvider, - logEnabled: Boolean, - apiVersion: String = STAGE_VERSION, - ): UtorgEnvironment = UtorgEnvironment( - baseUri = STAGE_BASE_URL, - sidValue = authProvider.sidValue, - apiVersion = apiVersion, - utorgApi = createApi(STAGE_BASE_URL, authProvider, logEnabled), - ) - - fun mock(): UtorgEnvironment = UtorgEnvironment( - baseUri = Uri.EMPTY, - sidValue = "", - apiVersion = "", - utorgApi = MockUtorgApi(), - ) - - private fun createApi(baseUri: Uri, authProvider: UtorgAuthProvider, logEnabled: Boolean): UtorgApi { - return createRetrofitInstance( - baseUrl = "$baseUri/", - interceptors = listOf(UtorgAuthHeaderInterceptor(authProvider)), - logEnabled = logEnabled, - ).create(UtorgApi::class.java) - } - } -} - -data class UtorgAuthProvider( - val sidValue: String, - val headerSidKey: String = "X-AUTH-SID", - val headerNonceKey: String = "X-AUTH-NONCE", -) { - val clientNonce: String - get() = UUID.randomUUID().toString() -} - -private class UtorgAuthHeaderInterceptor( - private val authProvider: UtorgAuthProvider, -) : Interceptor { - - override fun intercept(chain: Interceptor.Chain): Response { - val request = chain.request() - .newBuilder() - .addHeader(authProvider.headerSidKey, authProvider.sidValue) - .addHeader(authProvider.headerNonceKey, authProvider.clientNonce) - .build() - - return chain.proceed(request) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/UtorgExchangeService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/UtorgExchangeService.kt deleted file mode 100644 index 820751a14b..0000000000 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/UtorgExchangeService.kt +++ /dev/null @@ -1,116 +0,0 @@ -package com.tangem.tap.network.exchangeServices.utorg - -import android.net.Uri -import com.tangem.blockchain.common.Blockchain -import com.tangem.common.services.Result -import com.tangem.common.services.performRequest -import com.tangem.tap.common.redux.global.CryptoCurrencyName -import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager -import com.tangem.tap.network.exchangeServices.ExchangeService -import com.tangem.tap.network.exchangeServices.utorg.api.RequestSuccessUrl -import com.tangem.tap.network.exchangeServices.utorg.api.model.UtorgCurrencyData -import com.tangem.tap.network.exchangeServices.utorg.api.model.UtorgCurrencyType -import com.tangem.utils.converter.Converter - -/** -[REDACTED_AUTHOR] - */ -class UtorgExchangeService( - private val environment: UtorgEnvironment, - private val currencyConverter: Converter = ChainToBlockchainConverter(), -) : ExchangeService { - - private val api = environment.utorgApi - - private val utorgCurrencies = mutableListOf() - - override fun featureIsSwitchedOn(): Boolean = true - - override suspend fun update() { - when (val result = performRequest { api.getCurrency(environment.apiVersion) }) { - is Result.Success -> { - if (!result.data.isSuccess()) return - - val utorgCryptos = result.data.toSuccess().data.filter { - it.enabled && it.type == UtorgCurrencyType.CRYPTO - } - utorgCurrencies.clear() - utorgCurrencies.addAll(utorgCryptos) - - performRequest { - api.setSuccessUrl(environment.apiVersion, RequestSuccessUrl(environment.successUrl)) - } - } - is Result.Failure -> { - utorgCurrencies.clear() - } - } - } - - override fun isBuyAllowed(): Boolean = true - - override fun isSellAllowed(): Boolean = false - - override fun availableForBuy(currency: Currency): Boolean { - if (!isBuyAllowed()) return false - - val foundUtorgCurrency = utorgCurrencies.firstOrNull { utorgCurrency -> - val utorgBlockchain = currencyConverter.convert(utorgCurrency) ?: return@firstOrNull false - - val isSameBlockchain = utorgBlockchain == currency.blockchain - val isSameSymbol = utorgCurrency.symbol.lowercase() == currency.currencySymbol.lowercase() - isSameBlockchain && isSameSymbol - } - - return foundUtorgCurrency != null - } - - override fun availableForSell(currency: Currency): Boolean = false - - override fun getUrl( - action: CurrencyExchangeManager.Action, - blockchain: Blockchain, - cryptoCurrencyName: CryptoCurrencyName, - fiatCurrencyName: String, - walletAddress: String, - ): String { - if (action == CurrencyExchangeManager.Action.Sell) throw UnsupportedOperationException() - - // https://app-stage.utorg.pro/direct/testSID/mvmeaWyWiuVYdZdySgofAt6CmKhJbRhaWA/?¤cy=BTC - val builder = Uri.Builder() - .scheme(environment.baseUri.scheme) - .authority(environment.baseUri.authority) - .appendPath("direct") - .appendPath(environment.sidValue) - .appendPath(walletAddress) - .appendQueryParameter("currency", cryptoCurrencyName) - // if we set the paymentCurrency, then the Utorg widget didn't work - // .appendQueryParameter("paymentCurrency", "USD") - - val url = builder.build().toString() - return url - } - - override fun getSellCryptoReceiptUrl(action: CurrencyExchangeManager.Action, transactionId: String): String? = null -} - -private class ChainToBlockchainConverter : Converter { - override fun convert(value: UtorgCurrencyData): Blockchain? { - return when (value.chain?.uppercase()) { - "ARBITRUM" -> Blockchain.Arbitrum - "AVALANCHE" -> Blockchain.Avalanche - "BINANCE_SMART_CHAIN" -> Blockchain.BSC - "BITCOIN" -> Blockchain.Bitcoin - "BNB" -> Blockchain.Binance - "ETHEREUM" -> Blockchain.Ethereum - "GNOSIS" -> Blockchain.Gnosis - "POLYGON" -> Blockchain.Polygon - "RIPPLE" -> Blockchain.XRP - "RSK" -> Blockchain.RSK - "SOLANA" -> Blockchain.Solana - else -> null - // "APTOS", "ATOM", "NEAR", "ZKSYNC", "VECHAIN", "VELAS", "VELAS_EVM" -> null - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/api/UtorgApi.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/api/UtorgApi.kt deleted file mode 100644 index b18618e38b..0000000000 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/api/UtorgApi.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.tangem.tap.network.exchangeServices.utorg.api - -import com.squareup.moshi.Json -import com.tangem.tap.network.exchangeServices.utorg.api.model.UtorgCurrencyResponse -import retrofit2.http.Body -import retrofit2.http.POST -import retrofit2.http.Path - -/** -[REDACTED_AUTHOR] - */ -interface UtorgApi { - - @POST("api/merchant/{apiVersion}/settings/currency") - suspend fun getCurrency(@Path("apiVersion") apiVersion: String): UtorgCurrencyResponse - - @POST("api/merchant/{apiVersion}/settings/successUrl") - suspend fun setSuccessUrl(@Path("apiVersion") apiVersion: String, @Body request: RequestSuccessUrl) -} - -data class RequestSuccessUrl( - val url: String, -) - -interface UtorgResponse { - val success: Boolean - val timestamp: Long - val data: Data? - val error: UtorgErrorResponse? - - fun isSuccess(): Boolean = success && data != null && error == null - - @Throws(NullPointerException::class) - fun toSuccess(): UtorgSuccessResponse { - val internalTimestamp = this.timestamp - val internalData = this.data - - return object : UtorgSuccessResponse { - override val timestamp: Long = internalTimestamp - override val data: Data = internalData!! - } - } - - @Throws(NullPointerException::class) - fun toError(): UtorgErrorResponse = error!! -} - -interface UtorgSuccessResponse { - val timestamp: Long - val data: T -} - -data class UtorgErrorResponse( - @Json(name = "message") val message: String?, - @Json(name = "type") val type: UtorgErrorType, -) - -enum class UtorgErrorType { - UNAUTHORIZED, - UNKNOWN_ERROR, - BAD_REQUEST, -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/api/model/UtorgCurrencyResponse.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/api/model/UtorgCurrencyResponse.kt deleted file mode 100644 index 5df98687d8..0000000000 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/api/model/UtorgCurrencyResponse.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.tangem.tap.network.exchangeServices.utorg.api.model - -import com.squareup.moshi.Json -import com.tangem.tap.network.exchangeServices.utorg.api.UtorgErrorResponse -import com.tangem.tap.network.exchangeServices.utorg.api.UtorgResponse - -class UtorgCurrencyResponse( - @Json(name = "success") override val success: Boolean, - @Json(name = "timestamp") override val timestamp: Long, - @Json(name = "data") override val data: List?, - @Json(name = "error") override val error: UtorgErrorResponse?, -) : UtorgResponse> - -data class UtorgCurrencyData( - @Json(name = "currency") val currency: String, - @Json(name = "symbol") val symbol: String, - @Json(name = "enabled") val enabled: Boolean, - @Json(name = "type") val type: UtorgCurrencyType, - @Json(name = "caption") val caption: String?, - @Json(name = "chain") val chain: String?, -) - -enum class UtorgCurrencyType { - FIAT, CRYPTO -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/mock/MockUtorgApi.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/mock/MockUtorgApi.kt deleted file mode 100644 index e50b8b8833..0000000000 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/mock/MockUtorgApi.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.tangem.tap.network.exchangeServices.utorg.mock - -import com.tangem.common.json.MoshiJsonConverter -import com.tangem.tap.network.exchangeServices.utorg.api.RequestSuccessUrl -import com.tangem.tap.network.exchangeServices.utorg.api.UtorgApi -import com.tangem.tap.network.exchangeServices.utorg.api.UtorgErrorResponse -import com.tangem.tap.network.exchangeServices.utorg.api.UtorgErrorType -import com.tangem.tap.network.exchangeServices.utorg.api.model.UtorgCurrencyResponse -import kotlinx.coroutines.delay - -/** -[REDACTED_AUTHOR] - */ -class MockUtorgApi : UtorgApi { - - var nextDelay = 500L - - var nextResponseType = ResponseType.Success - var nextErrorType = UtorgErrorType.UNKNOWN_ERROR - - override suspend fun getCurrency(apiVersion: String): UtorgCurrencyResponse { - delay(nextDelay) - return UtorgCurrencyResponse( - success = createIsSuccess(), - timestamp = createTime(), - data = createData(MockUtorgSuccessDataResponse.GetCurrency), - error = createError(), - ) - } - - override suspend fun setSuccessUrl(apiVersion: String, request: RequestSuccessUrl) { - delay(nextDelay) - } - - private fun createIsSuccess(): Boolean = when (nextResponseType) { - ResponseType.Success -> true - ResponseType.Error -> false - } - - private fun createTime(): Long = System.currentTimeMillis() - - private inline fun createData(response: MockUtorgSuccessDataResponse): T? = when (nextResponseType) { - ResponseType.Success -> MoshiJsonConverter.INSTANCE.fromJson(response.json)!! - ResponseType.Error -> null - } - - private fun createError(): UtorgErrorResponse? = when (nextResponseType) { - ResponseType.Success -> null - ResponseType.Error -> UtorgErrorResponse( - message = "Optional message", - type = nextErrorType, - ) - } - - enum class ResponseType { - Success, Error - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/mock/MockUtorgSuccessDataResponse.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/mock/MockUtorgSuccessDataResponse.kt deleted file mode 100644 index 959e65a4d5..0000000000 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/mock/MockUtorgSuccessDataResponse.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tangem.tap.network.exchangeServices.utorg.mock - -import com.tangem.tap.network.exchangeServices.utorg.mock.json.getCurrencyFull - -/** -[REDACTED_AUTHOR] - */ -sealed class MockUtorgSuccessDataResponse( - val json: String, -) { - object GetCurrency : MockUtorgSuccessDataResponse(getCurrencyFull) -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/mock/json/CurrencyResponseJson.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/mock/json/CurrencyResponseJson.kt deleted file mode 100644 index 3d50462305..0000000000 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/mock/json/CurrencyResponseJson.kt +++ /dev/null @@ -1,1025 +0,0 @@ -package com.tangem.tap.network.exchangeServices.utorg.mock.json - -/** -[REDACTED_AUTHOR] - */ -internal val getCurrencyFull = """ -[ - { - "currency": "APT", - "symbol": "APT", - "chain": "APTOS", - "display": "APT", - "caption": "Aptos", - "explorerTx": "https://aptoscan.com/version/", - "explorerAddr": "https://aptoscan.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 1.8492, - "depositMax": 739.6673, - "withdrawalMin": 1.8492, - "withdrawalMax": 739.6673, - "addressValidator": "APT", - "precision": 4, - "allowTag": false - }, - { - "currency": "ATOM", - "symbol": "ATOM", - "chain": "ATOM", - "display": "ATOM", - "caption": "Cosmos", - "explorerTx": "https://atomscan.com/transactions/", - "explorerAddr": "https://atomscan.com/accounts/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 1.8020, - "depositMax": 720.7911, - "withdrawalMin": 1.8020, - "withdrawalMax": 720.7911, - "addressValidator": "COSMOS", - "precision": 4, - "allowTag": true, - "udKey": "crypto.ATOM.address" - }, - { - "currency": "AUD", - "symbol": "AUD", - "display": "AUD", - "type": "FIAT", - "enabled": true, - "depositMin": 43.73, - "depositMax": 15013.68, - "withdrawalMin": 43.73, - "withdrawalMax": 15013.68, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "AVAXAVA", - "symbol": "AVAX", - "chain": "AVALANCHE", - "display": "Avax", - "caption": "Avalanche", - "explorerTx": "", - "explorerAddr": "", - "type": "CRYPTO", - "enabled": true, - "depositMin": 1.337428, - "depositMax": 534.971102, - "withdrawalMin": 1.337428, - "withdrawalMax": 534.971102, - "addressValidator": "ETH", - "precision": 6, - "allowTag": false, - "udKey": "crypto.AVAX.address" - }, - { - "currency": "BNB", - "symbol": "BNB", - "chain": "BNB", - "display": "BNB", - "caption": "BEP2", - "explorerTx": "https://explorer.binance.org/tx/", - "explorerAddr": "https://explorer.binance.org/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 0.082738, - "depositMax": 33.095138, - "withdrawalMin": 0.082738, - "withdrawalMax": 33.095138, - "addressValidator": "BNB", - "precision": 6, - "allowTag": true, - "udKey": "crypto.BNB.address" - }, - { - "currency": "BNBBSC", - "symbol": "BNB", - "chain": "BINANCE_SMART_CHAIN", - "display": "BNB", - "caption": "BEP20", - "explorerTx": "https://www.bscscan.com/tx/", - "explorerAddr": "https://www.bscscan.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 0.0828, - "depositMax": 33.0951, - "withdrawalMin": 0.0828, - "withdrawalMax": 33.0951, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "BRL", - "symbol": "BRL", - "display": "BRL", - "type": "FIAT", - "enabled": true, - "depositMin": 158.08, - "depositMax": 54293.21, - "withdrawalMin": 158.08, - "withdrawalMax": 54293.21, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "BTC", - "symbol": "BTC", - "chain": "BITCOIN", - "display": "BTC", - "caption": "", - "explorerTx": "https://blockstream.info/tx/", - "explorerAddr": "https://blockstream.info/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 528764.805415, - "depositMax": 211505922.165820, - "withdrawalMin": 528764.805415, - "withdrawalMax": 211505922.165820, - "addressValidator": "BTC", - "precision": 6, - "allowTag": false, - "udKey": "crypto.BTC.address" - }, - { - "currency": "BUSDAVA", - "symbol": "BUSD", - "chain": "AVALANCHE", - "display": "BUSD", - "caption": "on Avalanche", - "explorerTx": "https://snowtrace.io/tx/", - "explorerAddr": "https://snowtrace.io/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6382, - "depositMax": 10655.2775, - "withdrawalMin": 26.6382, - "withdrawalMax": 10655.2775, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "BUSDBSC", - "symbol": "BUSD", - "chain": "BINANCE_SMART_CHAIN", - "display": "BUSD", - "caption": "BEP20", - "explorerTx": "https://www.bscscan.com/tx/", - "explorerAddr": "https://www.bscscan.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6414, - "depositMax": 10656.5563, - "withdrawalMin": 26.6414, - "withdrawalMax": 10656.5563, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false, - "udKey": "crypto.BUSD.version.BEP20.address" - }, - { - "currency": "BUSDETH", - "symbol": "BUSD", - "chain": "ETHEREUM", - "display": "BUSD", - "caption": "ERC20", - "explorerTx": "https://etherscan.io/tx/", - "explorerAddr": "https://etherscan.io/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6414, - "depositMax": 10656.5563, - "withdrawalMin": 26.6414, - "withdrawalMax": 10656.5563, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false, - "udKey": "crypto.BUSD.version.ERC20.address" - }, - { - "currency": "CAD", - "symbol": "CAD", - "display": "CAD", - "type": "FIAT", - "enabled": true, - "depositMin": 40.85, - "depositMax": 14024.33, - "withdrawalMin": 40.85, - "withdrawalMax": 14024.33, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "CZK", - "symbol": "CZK", - "display": "CZK", - "type": "FIAT", - "enabled": true, - "depositMin": 672.71, - "depositMax": 231068.12, - "withdrawalMin": 672.71, - "withdrawalMax": 231068.12, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "DAIBSC", - "symbol": "DAI", - "chain": "BINANCE_SMART_CHAIN", - "display": "DAI", - "caption": "BEP20", - "explorerTx": "https://www.bscscan.com/tx/", - "explorerAddr": "https://www.bscscan.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6462, - "depositMax": 10658.4634, - "withdrawalMin": 26.6462, - "withdrawalMax": 10658.4634, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "DAIEAVA", - "symbol": "DAIE", - "chain": "AVALANCHE", - "display": "DAI.e", - "caption": "on Avalanche", - "explorerTx": "https://snowtrace.io/tx/", - "explorerAddr": "https://snowtrace.io/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6052, - "depositMax": 10642.0513, - "withdrawalMin": 26.6052, - "withdrawalMax": 10642.0513, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "DAIETH", - "symbol": "DAI", - "chain": "ETHEREUM", - "display": "DAI", - "caption": "ERC20", - "explorerTx": "https://etherscan.io/tx/", - "explorerAddr": "https://etherscan.io/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6436, - "depositMax": 10657.4090, - "withdrawalMin": 26.6436, - "withdrawalMax": 10657.4090, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false, - "udKey": "crypto.DAI.address" - }, - { - "currency": "DAIPOL", - "symbol": "DAI", - "chain": "POLYGON", - "display": "DAI", - "caption": "on Polygon", - "explorerTx": "https://polygonscan.com/tx/", - "explorerAddr": "https://polygonscan.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6436, - "depositMax": 10657.4090, - "withdrawalMin": 26.6436, - "withdrawalMax": 10657.4090, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "DKK", - "symbol": "DKK", - "display": "DKK", - "type": "FIAT", - "enabled": true, - "depositMin": 210.64, - "depositMax": 72348.14, - "withdrawalMin": 210.64, - "withdrawalMax": 72348.14, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "ETH", - "symbol": "ETH", - "chain": "ETHEREUM", - "display": "ETH", - "caption": "", - "explorerTx": "https://ropsten.etherscan.io/tx/", - "explorerAddr": "https://ropsten.etherscan.io/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 37688.767964, - "depositMax": 15075507.185288, - "withdrawalMin": 37688.767964, - "withdrawalMax": 15075507.185288, - "addressValidator": "ETH", - "precision": 6, - "allowTag": false, - "udKey": "crypto.ETH.address" - }, - { - "currency": "EUR", - "symbol": "EUR", - "display": "EUR", - "caption": "", - "type": "FIAT", - "enabled": true, - "depositMin": 27.24, - "depositMax": 9349.53, - "withdrawalMin": 27.24, - "withdrawalMax": 9349.53, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "GBP", - "symbol": "GBP", - "display": "GBP", - "type": "FIAT", - "enabled": true, - "depositMin": 25.14, - "depositMax": 8630.60, - "withdrawalMin": 25.14, - "withdrawalMax": 8630.60, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "GMTBSC", - "symbol": "GMT", - "chain": "BINANCE_SMART_CHAIN", - "display": "GMT", - "caption": "BEP20", - "explorerTx": "https://bscscan.com/tx/", - "explorerAddr": "https://bscscan.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 53.9899, - "depositMax": 21595.9496, - "withdrawalMin": 53.9899, - "withdrawalMax": 21595.9496, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "GNOETH", - "symbol": "GNO", - "chain": "ETHEREUM", - "display": "GNO", - "caption": "ERC20", - "explorerTx": "https://etherscan.io/tx/", - "explorerAddr": "https://etherscan.io/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 0.2250, - "depositMax": 89.9938, - "withdrawalMin": 0.2250, - "withdrawalMax": 89.9938, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false, - "udKey": "crypto.GNO.address" - }, - { - "currency": "HAIBSC", - "symbol": "HAI", - "chain": "BINANCE_SMART_CHAIN", - "display": "HAI", - "caption": "on BSC", - "explorerTx": "https://bscscan.com/tx/", - "explorerAddr": "https://bscscan.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 937.548948, - "depositMax": 375019.579098, - "withdrawalMin": 937.548948, - "withdrawalMax": 375019.579098, - "addressValidator": "ETH", - "precision": 6, - "allowTag": false - }, - { - "currency": "HAIVET", - "symbol": "HAI", - "chain": "VECHAIN", - "display": "HAI", - "caption": "VET", - "explorerTx": "https://vechainstats.com/transaction/", - "explorerAddr": "https://vechainstats.com/account/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 949.3974, - "depositMax": 379758.9569, - "withdrawalMin": 949.3974, - "withdrawalMax": 379758.9569, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "IDR", - "symbol": "IDR", - "display": "IDR", - "type": "FIAT", - "enabled": true, - "depositMin": 459558, - "depositMax": 157855988, - "withdrawalMin": 459558, - "withdrawalMax": 157855988, - "addressValidator": "LUHN", - "precision": 0, - "allowTag": false - }, - { - "currency": "INR", - "symbol": "INR", - "display": "INR", - "type": "FIAT", - "enabled": true, - "depositMin": 2511.35, - "depositMax": 862635.95, - "withdrawalMin": 2511.35, - "withdrawalMax": 862635.95, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "JPY", - "symbol": "JPY", - "display": "JPY", - "type": "FIAT", - "enabled": true, - "depositMin": 3992, - "depositMax": 1370884, - "withdrawalMin": 3992, - "withdrawalMax": 1370884, - "addressValidator": "LUHN", - "precision": 0, - "allowTag": false - }, - { - "currency": "KZT", - "symbol": "KZT", - "display": "KZT", - "type": "FIAT", - "enabled": true, - "depositMin": 13843.18, - "depositMax": 4755080.66, - "withdrawalMin": 13843.18, - "withdrawalMax": 4755080.66, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "MH3ETH", - "symbol": "MH3", - "chain": "ETHEREUM", - "display": "NFT", - "caption": "Meta History", - "explorerTx": "https://rinkeby.etherscan.io/tx/", - "explorerAddr": "https://rinkeby.etherscan.io/address/", - "type": "CRYPTO", - "enabled": false, - "depositMin": 0, - "depositMax": 0, - "withdrawalMin": 0, - "withdrawalMax": 0, - "addressValidator": "ETH", - "precision": 0, - "allowTag": false, - "nftContract": "0xf0192b97135abaa218bcff255b8f4b22171a7590" - }, - { - "currency": "MXN", - "symbol": "MXN", - "display": "MXN", - "type": "FIAT", - "enabled": true, - "depositMin": 574.83, - "depositMax": 197445.63, - "withdrawalMin": 574.83, - "withdrawalMax": 197445.63, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "MYR", - "symbol": "MYR", - "display": "MYR", - "type": "FIAT", - "enabled": true, - "depositMin": 131.04, - "depositMax": 45006.86, - "withdrawalMin": 131.04, - "withdrawalMax": 45006.86, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "NEAR", - "symbol": "NEAR", - "chain": "NEAR", - "display": "NEAR", - "caption": "", - "explorerTx": "", - "explorerAddr": "", - "type": "CRYPTO", - "enabled": true, - "depositMin": 10.560163, - "depositMax": 4224.064906, - "withdrawalMin": 10.560163, - "withdrawalMax": 4224.064906, - "addressValidator": "NEAR", - "precision": 6, - "allowTag": false, - "udKey": "crypto.NEAR.address" - }, - { - "currency": "NOK", - "symbol": "NOK", - "display": "NOK", - "type": "FIAT", - "enabled": true, - "depositMin": 312.23, - "depositMax": 107245.60, - "withdrawalMin": 312.23, - "withdrawalMax": 107245.60, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "NXUSDAVA", - "symbol": "NXUSD", - "chain": "AVALANCHE", - "display": "NXUSD", - "caption": "Avalanche", - "explorerTx": "https://snowtrace.io/tx/", - "explorerAddr": "https://snowtrace.io/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.8766, - "depositMax": 10750.6217, - "withdrawalMin": 26.8766, - "withdrawalMax": 10750.6217, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "NZD", - "symbol": "NZD", - "display": "NZD", - "type": "FIAT", - "enabled": true, - "depositMin": 47.90, - "depositMax": 16448.49, - "withdrawalMin": 47.90, - "withdrawalMax": 16448.49, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "PLN", - "symbol": "PLN", - "display": "PLN", - "type": "FIAT", - "enabled": true, - "depositMin": 134.06, - "depositMax": 46047.85, - "withdrawalMin": 134.06, - "withdrawalMax": 46047.85, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "RIF", - "symbol": "RIF", - "chain": "RSK", - "display": "RIF", - "caption": "RSK", - "explorerTx": "https://explorer.rsk.co/tx/", - "explorerAddr": "https://explorer.rsk.co/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 429.65, - "depositMax": 171859.31, - "withdrawalMin": 429.65, - "withdrawalMax": 171859.31, - "addressValidator": "ETH", - "precision": 2, - "allowTag": false, - "udKey": "crypto.RIF.address" - }, - { - "currency": "RUB", - "symbol": "RUB", - "display": "RUB", - "type": "FIAT", - "enabled": true, - "depositMin": 2217.40, - "depositMax": 761666.68, - "withdrawalMin": 2217.40, - "withdrawalMax": 761666.68, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "SOL", - "symbol": "SOL", - "chain": "SOLANA", - "display": "SOL", - "caption": "Solana", - "explorerTx": "https://explorer.solana.com/tx/", - "explorerAddr": "https://explorer.solana.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 1.155094, - "depositMax": 462.037519, - "withdrawalMin": 1.155094, - "withdrawalMax": 462.037519, - "addressValidator": "SOLANA", - "precision": 6, - "allowTag": false, - "udKey": "crypto.SOL.address" - }, - { - "currency": "TRY", - "symbol": "TRY", - "display": "TRY", - "type": "FIAT", - "enabled": true, - "depositMin": 572.28, - "depositMax": 196571.08, - "withdrawalMin": 572.28, - "withdrawalMax": 196571.08, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "TWTBNB", - "symbol": "TWT", - "chain": "BNB", - "display": "TWT", - "caption": "BEP2", - "explorerTx": "https://explorer.binance.org/tx/", - "explorerAddr": "https://explorer.binance.org/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 17.4457, - "depositMax": 6978.2637, - "withdrawalMin": 17.4457, - "withdrawalMax": 6978.2637, - "addressValidator": "BNB", - "precision": 4, - "allowTag": true, - "udKey": "crypto.TWT.address" - }, - { - "currency": "UAH", - "symbol": "UAH", - "display": "UAH", - "caption": "", - "type": "FIAT", - "enabled": true, - "depositMin": 1118.00, - "depositMax": 14005.59, - "withdrawalMin": 1118.00, - "withdrawalMax": 14005.59, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "USD", - "symbol": "USD", - "display": "USD", - "type": "FIAT", - "enabled": true, - "depositMin": 30.57, - "depositMax": 10382.96, - "withdrawalMin": 30.57, - "withdrawalMax": 10382.96, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - }, - { - "currency": "USDCARB", - "symbol": "USDC", - "chain": "ARBITRUM", - "display": "USDC", - "caption": "on arbitrum", - "explorerTx": "https://arbiscan.io/tx/", - "explorerAddr": "https://arbiscan.io/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6382, - "depositMax": 10655.2775, - "withdrawalMin": 26.6382, - "withdrawalMax": 10655.2775, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "USDCBSC", - "symbol": "USDC", - "chain": "BINANCE_SMART_CHAIN", - "display": "USDC", - "caption": "BEP20", - "explorerTx": "https://www.bscscan.com/tx/", - "explorerAddr": "https://www.bscscan.com/address/", - "type": "CRYPTO", - "enabled": false, - "depositMin": 0, - "depositMax": 0, - "withdrawalMin": 0, - "withdrawalMax": 0, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "USDCEAVA", - "symbol": "USDCE", - "chain": "AVALANCHE", - "display": "USDC.e", - "caption": "on Avalanche", - "explorerTx": "", - "explorerAddr": "", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6078, - "depositMax": 10643.1155, - "withdrawalMin": 26.6078, - "withdrawalMax": 10643.1155, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "USDCETH", - "symbol": "USDC", - "chain": "ETHEREUM", - "display": "USDC", - "caption": "ERC20", - "explorerTx": "https://etherscan.io/tx/", - "explorerAddr": "https://etherscan.io/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6382, - "depositMax": 10655.2775, - "withdrawalMin": 26.6382, - "withdrawalMax": 10655.2775, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false, - "udKey": "crypto.USDC.address" - }, - { - "currency": "USDCZK", - "symbol": "USDC", - "chain": "ZKSYNC", - "display": "USDC", - "caption": "on zkSync", - "explorerTx": "https://zkscan.io/explorer/transactions/", - "explorerAddr": "https://zkscan.io/explorer/accounts/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6078, - "depositMax": 10643.1155, - "withdrawalMin": 26.6078, - "withdrawalMax": 10643.1155, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "USDTAVA", - "symbol": "USDT", - "chain": "AVALANCHE", - "display": "USDT", - "caption": "on Avalanche", - "explorerTx": "https://snowtrace.io/tx/", - "explorerAddr": "https://snowtrace.io/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6649, - "depositMax": 10665.9328, - "withdrawalMin": 26.6649, - "withdrawalMax": 10665.9328, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "USDTE", - "symbol": "USDT", - "chain": "ETHEREUM", - "display": "USDT", - "caption": "", - "explorerTx": "", - "explorerAddr": "", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.66483213, - "depositMax": 10665.93285048, - "withdrawalMin": 26.66483213, - "withdrawalMax": 10665.93285048, - "addressValidator": "ETH", - "precision": 8, - "allowTag": false, - "udKey": "crypto.USDT.version.ERC20.address" - }, - { - "currency": "USDTPOL", - "symbol": "USDT", - "chain": "POLYGON", - "display": "USDT", - "caption": "on Polygon", - "explorerTx": "https://polygonscan.com/tx/", - "explorerAddr": "https://polygonscan.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6649, - "depositMax": 10665.9328, - "withdrawalMin": 26.6649, - "withdrawalMax": 10665.9328, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "USDVEL", - "symbol": "USDV", - "chain": "VELAS_EVM", - "display": "USDV", - "caption": "Velas EVM", - "explorerTx": "https://evmexplorer.velas.com/tx/", - "explorerAddr": "https://evmexplorer.velas.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26611608.908400, - "depositMax": 10644643563.359833, - "withdrawalMin": 26611608.908400, - "withdrawalMax": 10644643563.359833, - "addressValidator": "ETH", - "precision": 6, - "allowTag": false - }, - { - "currency": "USNNEAR", - "symbol": "USN", - "chain": "NEAR", - "display": "USN", - "caption": "Near", - "explorerTx": "https://explorer.near.org/transactions/", - "explorerAddr": "https://explorer.near.org/accounts/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6969, - "depositMax": 10678.7473, - "withdrawalMin": 26.6969, - "withdrawalMax": 10678.7473, - "addressValidator": "NEAR", - "precision": 4, - "allowTag": false - }, - { - "currency": "VLX", - "symbol": "VLX", - "chain": "VELAS", - "display": "VLX", - "caption": "Velas", - "explorerTx": "https://explorer.velas.com/tx/", - "explorerAddr": "https://explorer.velas.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 1021.951187, - "depositMax": 408780.474783, - "withdrawalMin": 1021.951187, - "withdrawalMax": 408780.474783, - "addressValidator": "SOLANA", - "precision": 6, - "allowTag": false, - "udKey": "crypto.VLX.address" - }, - { - "currency": "VLXETH", - "symbol": "VLX", - "chain": "VELAS_EVM", - "display": "VLX", - "caption": "Velas EVM", - "explorerTx": "https://evmexplorer.velas.com/tx/", - "explorerAddr": "https://evmexplorer.velas.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 1021.9512, - "depositMax": 408780.4747, - "withdrawalMin": 1021.9512, - "withdrawalMax": 408780.4747, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "WLKNSOL", - "symbol": "WLKN", - "chain": "SOLANA", - "display": "WLKN", - "caption": "Solana", - "explorerTx": "https://explorer.solana.com/tx/", - "explorerAddr": "https://explorer.solana.com/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 531.89, - "depositMax": 212755.45, - "withdrawalMin": 531.89, - "withdrawalMax": 212755.45, - "addressValidator": "SOLANA", - "precision": 2, - "allowTag": false - }, - { - "currency": "XDAIGNO", - "symbol": "xDAI", - "chain": "GNOSIS", - "display": "xDAI", - "caption": "Gnosis chain", - "explorerTx": "https://blockscout.com/xdai/mainnet/tx/", - "explorerAddr": "https://blockscout.com/xdai/mainnet/address/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 26.6782, - "depositMax": 10671.2684, - "withdrawalMin": 26.6782, - "withdrawalMax": 10671.2684, - "addressValidator": "ETH", - "precision": 4, - "allowTag": false - }, - { - "currency": "XRP", - "symbol": "XRP", - "chain": "RIPPLE", - "display": "XRP", - "caption": "Ripple", - "explorerTx": "https://xrpscan.com/tx/", - "explorerAddr": "https://xrpscan.com/account/", - "type": "CRYPTO", - "enabled": true, - "depositMin": 67.7645, - "depositMax": 27105.7684, - "withdrawalMin": 67.7645, - "withdrawalMax": 27105.7684, - "addressValidator": "XRP", - "precision": 4, - "allowTag": true, - "udKey": "crypto.XRP.address" - }, - { - "currency": "ZAR", - "symbol": "ZAR", - "display": "ZAR", - "type": "FIAT", - "enabled": true, - "depositMin": 538.27, - "depositMax": 184892.03, - "withdrawalMin": 538.27, - "withdrawalMax": 184892.03, - "addressValidator": "LUHN", - "precision": 2, - "allowTag": false - } - ] -""".trimIndent() \ No newline at end of file diff --git a/app/src/main/res/color/selector_saltpay_btn.xml b/app/src/main/res/color/selector_saltpay_btn.xml deleted file mode 100644 index 98dd6f0aba..0000000000 --- a/app/src/main/res/color/selector_saltpay_btn.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/selector_saltpay_btn_text.xml b/app/src/main/res/color/selector_saltpay_btn_text.xml deleted file mode 100644 index 28e2f2cfdd..0000000000 --- a/app/src/main/res/color/selector_saltpay_btn_text.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/img_salt_pay_visa.png b/app/src/main/res/drawable/img_salt_pay_visa.png deleted file mode 100644 index 02b199c1e5..0000000000 Binary files a/app/src/main/res/drawable/img_salt_pay_visa.png and /dev/null differ diff --git a/app/src/main/res/layout-h680dp/layout_onboarding_saltpay_kyc_in_progress.xml b/app/src/main/res/layout-h680dp/layout_onboarding_saltpay_kyc_in_progress.xml deleted file mode 100644 index 34b57671aa..0000000000 --- a/app/src/main/res/layout-h680dp/layout_onboarding_saltpay_kyc_in_progress.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_onboarding_wallet.xml b/app/src/main/res/layout/fragment_onboarding_wallet.xml index 59a23e9ab4..821f0d3ef8 100644 --- a/app/src/main/res/layout/fragment_onboarding_wallet.xml +++ b/app/src/main/res/layout/fragment_onboarding_wallet.xml @@ -221,13 +221,6 @@ - - - \ No newline at end of file + diff --git a/app/src/main/res/layout/fragment_wallet.xml b/app/src/main/res/layout/fragment_wallet.xml index 6f1a62cabf..b4287625d4 100644 --- a/app/src/main/res/layout/fragment_wallet.xml +++ b/app/src/main/res/layout/fragment_wallet.xml @@ -177,15 +177,6 @@ android:visibility="gone" app:layout_constraintTop_toBottomOf="@id/rv_pending_transaction" /> - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/item_salt_pay_tx_history_date.xml b/app/src/main/res/layout/item_salt_pay_tx_history_date.xml deleted file mode 100644 index a21c2dbd6e..0000000000 --- a/app/src/main/res/layout/item_salt_pay_tx_history_date.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/app/src/main/res/layout/item_salt_pay_tx_history_shimmer.xml b/app/src/main/res/layout/item_salt_pay_tx_history_shimmer.xml deleted file mode 100644 index 72aff47fa0..0000000000 --- a/app/src/main/res/layout/item_salt_pay_tx_history_shimmer.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/layout_onboarding_saltpay.xml b/app/src/main/res/layout/layout_onboarding_saltpay.xml deleted file mode 100644 index fbb3534b9b..0000000000 --- a/app/src/main/res/layout/layout_onboarding_saltpay.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/layout_onboarding_saltpay_connect_card.xml b/app/src/main/res/layout/layout_onboarding_saltpay_connect_card.xml deleted file mode 100644 index 5e3ff40fb1..0000000000 --- a/app/src/main/res/layout/layout_onboarding_saltpay_connect_card.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/layout_onboarding_saltpay_kyc_in_progress.xml b/app/src/main/res/layout/layout_onboarding_saltpay_kyc_in_progress.xml deleted file mode 100644 index 0114973c36..0000000000 --- a/app/src/main/res/layout/layout_onboarding_saltpay_kyc_in_progress.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/layout_onboarding_saltpay_kyc_start.xml b/app/src/main/res/layout/layout_onboarding_saltpay_kyc_start.xml deleted file mode 100644 index 4a9ef0a9e2..0000000000 --- a/app/src/main/res/layout/layout_onboarding_saltpay_kyc_start.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/layout_onboarding_saltpay_pin_code.xml b/app/src/main/res/layout/layout_onboarding_saltpay_pin_code.xml deleted file mode 100644 index 96562a0c1f..0000000000 --- a/app/src/main/res/layout/layout_onboarding_saltpay_pin_code.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/layout_salt_pay_balance.xml b/app/src/main/res/layout/layout_salt_pay_balance.xml deleted file mode 100644 index 8ce65d0b6b..0000000000 --- a/app/src/main/res/layout/layout_salt_pay_balance.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/layout_salt_pay_tx_history.xml b/app/src/main/res/layout/layout_salt_pay_tx_history.xml deleted file mode 100644 index 2aef592910..0000000000 --- a/app/src/main/res/layout/layout_salt_pay_tx_history.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/layout_salt_pay_wallet.xml b/app/src/main/res/layout/layout_salt_pay_wallet.xml deleted file mode 100644 index 4712e76937..0000000000 --- a/app/src/main/res/layout/layout_salt_pay_wallet.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index ae38fdcf4a..6c451317c2 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -103,19 +103,6 @@ 4sp - -