diff --git a/core/datasource/src/main/java/com/tangem/datasource/utils/NetworkLogsSaveInterceptor.kt b/core/datasource/src/main/java/com/tangem/datasource/utils/NetworkLogsSaveInterceptor.kt index 58b21f35dd..9e3d88dcb4 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/utils/NetworkLogsSaveInterceptor.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/utils/NetworkLogsSaveInterceptor.kt @@ -44,7 +44,12 @@ class NetworkLogsSaveInterceptor( throw e } - if (restrictedForLogURLs.contains(request.url.host + request.url.encodedPath)) { + val host = request.url.host + val path = request.url.encodedPath + val isRestrictedUrl = restrictedForLogURLs.contains(host + path) + val isRestrictedHost = restrictedForLogHosts.any { host.contains(it) } + + if (isRestrictedUrl || isRestrictedHost) { logResponseWithEmptyMessage(response, startNs) } else { logResponseMessage(response, startNs) @@ -222,5 +227,8 @@ class NetworkLogsSaveInterceptor( val restrictedForLogURLs = listOf( "api.stakek.it/v1/yields/enabled", ) + val restrictedForLogHosts = listOf( + "us.paera.com", + ) } } \ No newline at end of file diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 7f0604d2d7..97beabdc7a 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -1453,6 +1453,7 @@ Failed to issue card A technical error has occurred, please try again by clicking the button below. A technical error has occurred, please contact support. + Go to Support It usually takes up to 15 minutes Setting up your Tangem Card Issuing your card diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayCryptoCurrencyFactory.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayCryptoCurrencyFactory.kt index a768bf84b1..505383a099 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayCryptoCurrencyFactory.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayCryptoCurrencyFactory.kt @@ -2,14 +2,12 @@ package com.tangem.data.pay import arrow.core.Either import arrow.core.Either.Companion.catch -import com.squareup.moshi.Moshi import com.tangem.blockchain.blockchains.ethereum.Chain import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.core.error.UniversalError import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.data.common.network.NetworkFactory import com.tangem.data.pay.util.TangemPayErrorConverter -import com.tangem.datasource.di.NetworkMoshi import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.pay.TangemPayCryptoCurrencyFactory @@ -26,8 +24,8 @@ private const val TOKEN_CONTRACT_ADDRESS = "0x3c499c542cef5e3811e1192ce70d8cc03d private const val TOKEN_DECIMALS = 6 internal class DefaultTangemPayCryptoCurrencyFactory @Inject constructor( - @NetworkMoshi moshi: Moshi, excludedBlockchains: ExcludedBlockchains, + private val errorConverter: TangemPayErrorConverter, ) : TangemPayCryptoCurrencyFactory { private val cryptoCurrencyFactory by lazy(mode = LazyThreadSafetyMode.NONE) { @@ -37,8 +35,6 @@ internal class DefaultTangemPayCryptoCurrencyFactory @Inject constructor( NetworkFactory(excludedBlockchains) } - private val errorConverter by lazy(mode = LazyThreadSafetyMode.NONE) { TangemPayErrorConverter(moshi) } - override fun create(userWallet: UserWallet, chainId: Int): Either { return catch { val chain = requireNotNull(Chain.entries.find { it.id == chainId }) { "Can not find chain with $chainId" } diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt index 8af56ff827..1dafcfd572 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt @@ -1,8 +1,12 @@ package com.tangem.data.pay.repository import arrow.core.Either +import arrow.core.left +import arrow.core.raise.catch +import arrow.core.right import com.tangem.core.error.UniversalError import com.tangem.data.pay.util.RainCryptoUtil +import com.tangem.data.pay.util.TangemPayErrorConverter import com.tangem.data.visa.config.VisaLibLoader import com.tangem.datasource.api.common.config.ApiConfig import com.tangem.datasource.api.common.config.ApiEnvironment @@ -40,6 +44,7 @@ internal class DefaultTangemPayCardDetailsRepository @Inject constructor( private val rainCryptoUtil: RainCryptoUtil, private val storage: TangemPayStorage, private val cardFrozenStateStore: TangemPayCardFrozenStateStore, + private val errorConverter: TangemPayErrorConverter, ) : TangemPayCardDetailsRepository { private val pollingScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) @@ -64,37 +69,39 @@ internal class DefaultTangemPayCardDetailsRepository @Inject constructor( } override suspend fun revealCardDetails(userWalletId: UserWalletId): Either { - return requestHelper.runWithErrorLogs(TAG) { - val publicKeyBase64 = getPublicKeyBase64() - val (secretKeyBytes, sessionId) = rainCryptoUtil.generateSecretKeyAndSessionId(publicKeyBase64) + return catch( + block = { + val publicKeyBase64 = getPublicKeyBase64() + val (secretKeyBytes, sessionId) = rainCryptoUtil.generateSecretKeyAndSessionId(publicKeyBase64) + val result = requestHelper.performRequest(userWalletId = userWalletId) { authHeader -> + tangemPayApi.revealCardDetails( + authHeader = authHeader, + body = CardDetailsRequest(sessionId = sessionId), + ) + }.getOrNull()?.result ?: error("Cannot reveal card details") - val result = requestHelper.request(userWalletId) { authHeader -> - tangemPayApi.revealCardDetails( - authHeader = authHeader, - body = CardDetailsRequest(sessionId = sessionId), + val pan = rainCryptoUtil.decryptSecret( + base64Secret = result.pan.secret, + base64Iv = result.pan.iv, + secretKeyBytes = secretKeyBytes, ) - }.result ?: error("Cannot reveal card details") - val pan = rainCryptoUtil.decryptSecret( - base64Secret = result.pan.secret, - base64Iv = result.pan.iv, - secretKeyBytes = secretKeyBytes, - ) + val cvv = rainCryptoUtil.decryptSecret( + base64Secret = result.cvv.secret, + base64Iv = result.cvv.iv, + secretKeyBytes = secretKeyBytes, + ) + secretKeyBytes.fill(0) - val cvv = rainCryptoUtil.decryptSecret( - base64Secret = result.cvv.secret, - base64Iv = result.cvv.iv, - secretKeyBytes = secretKeyBytes, - ) - secretKeyBytes.fill(0) - - TangemPayCardDetails( - pan = pan, - cvv = cvv, - expirationYear = result.expirationYear, - expirationMonth = result.expirationMonth, - ) - } + TangemPayCardDetails( + pan = pan, + cvv = cvv, + expirationYear = result.expirationYear, + expirationMonth = result.expirationMonth, + ).right() + }, + catch = { errorConverter.convert(it).left() }, + ) } override suspend fun setPin(userWalletId: UserWalletId, pin: String): Either { diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/TangemPayRequestPerformer.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/TangemPayRequestPerformer.kt index 7e6b5ec06c..788aafe9d8 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/TangemPayRequestPerformer.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/TangemPayRequestPerformer.kt @@ -5,14 +5,12 @@ import arrow.core.getOrElse import arrow.core.left import arrow.core.raise.catch import arrow.core.right -import com.squareup.moshi.Moshi import com.squareup.wire.Instant import com.tangem.data.pay.util.TangemPayErrorConverter import com.tangem.datasource.api.common.response.ApiResponse import com.tangem.datasource.api.pay.TangemPayAuthApi import com.tangem.datasource.api.pay.models.request.RefreshCustomerWalletAccessTokenRequest import com.tangem.datasource.api.pay.models.response.TangemPayGetTokensResponse -import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.visa.TangemPayStorage import com.tangem.domain.models.wallet.UserWalletId @@ -33,7 +31,7 @@ private const val TAG = "TangemPayRequestPerformer" @Singleton internal class TangemPayRequestPerformer @Inject constructor( - @NetworkMoshi moshi: Moshi, + private val errorConverter: TangemPayErrorConverter, private val environmentConfigStorage: EnvironmentConfigStorage, private val dispatchers: CoroutineDispatcherProvider, private val tangemPayAuthApi: TangemPayAuthApi, @@ -42,7 +40,6 @@ internal class TangemPayRequestPerformer @Inject constructor( private val customerWalletAddresses = ConcurrentHashMap() private val tokensMutex = Mutex() - private val errorConverter = TangemPayErrorConverter(moshi) @Deprecated("Do not use this method") suspend fun runWithErrorLogs(tag: String, requestBlock: suspend () -> T): Either { diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/util/TangemPayErrorConverter.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/util/TangemPayErrorConverter.kt index 145269f0f5..8080f3b642 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/util/TangemPayErrorConverter.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/util/TangemPayErrorConverter.kt @@ -3,10 +3,16 @@ package com.tangem.data.pay.util import com.squareup.moshi.Moshi import com.tangem.datasource.api.common.response.ApiResponseError import com.tangem.datasource.api.pay.models.response.VisaErrorResponse +import com.tangem.datasource.di.NetworkMoshi import com.tangem.domain.visa.error.VisaApiError import com.tangem.utils.converter.Converter +import javax.inject.Inject +import javax.inject.Singleton -class TangemPayErrorConverter(moshi: Moshi) : Converter { +@Singleton +internal class TangemPayErrorConverter @Inject constructor( + @NetworkMoshi moshi: Moshi, +) : Converter { private val visaErrorAdapter by lazy { moshi.adapter(VisaErrorResponse::class.java) } diff --git a/domain/feedback/models/src/main/kotlin/com/tangem/domain/feedback/models/FeedbackEmailType.kt b/domain/feedback/models/src/main/kotlin/com/tangem/domain/feedback/models/FeedbackEmailType.kt index 78848710c5..520f49e395 100644 --- a/domain/feedback/models/src/main/kotlin/com/tangem/domain/feedback/models/FeedbackEmailType.kt +++ b/domain/feedback/models/src/main/kotlin/com/tangem/domain/feedback/models/FeedbackEmailType.kt @@ -57,7 +57,6 @@ sealed interface FeedbackEmailType { } sealed class Visa : FeedbackEmailType { - data class FailedIssueCard(override val walletMetaInfo: WalletMetaInfo) : Visa() data class DirectUserRequest(override val walletMetaInfo: WalletMetaInfo) : Visa() @@ -68,6 +67,8 @@ sealed interface FeedbackEmailType { override val walletMetaInfo: WalletMetaInfo, ) : Visa() + data class FailedIssueCard(override val walletMetaInfo: WalletMetaInfo) : Visa() + data class DisputeV2( val item: TangemPayTxHistoryItem, override val walletMetaInfo: WalletMetaInfo, diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt index 9a3a7de9b6..00815bea99 100644 --- a/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt +++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt @@ -12,6 +12,7 @@ internal class FeedbackDataBuilder { fun addTangemPayTxInfo(item: TangemPayTxHistoryItem) { builder.append(item.jsonRepresentation) + builder.breakLine() } fun addVisaTxInfo(txDetails: VisaTxDetails) { @@ -108,6 +109,26 @@ internal class FeedbackDataBuilder { builder.appendKeyValue("App version", phoneInfo.appVersion) } + fun addTangemPayIssueType(type: FeedbackEmailType.Visa) { + val issueType = when (type) { + is FeedbackEmailType.Visa.Activation, + is FeedbackEmailType.Visa.DirectUserRequest, + is FeedbackEmailType.Visa.Dispute, + is FeedbackEmailType.Visa.FeatureIsBeta, + is FeedbackEmailType.Visa.Withdrawal, + -> return + is FeedbackEmailType.Visa.DisputeV2 -> when (type.item) { + is TangemPayTxHistoryItem.Collateral -> "Receive/Withdraw" + is TangemPayTxHistoryItem.Fee, + is TangemPayTxHistoryItem.Spend, + is TangemPayTxHistoryItem.Payment, + -> "Transaction" + } + is FeedbackEmailType.Visa.FailedIssueCard -> "Card issuing" + } + builder.appendKeyValue("Issue type", issueType) + } + fun addBlockchainError(info: BlockchainInfo, error: BlockchainErrorInfo) { builder.appendKeyValue("Blockchain", info.blockchain) builder.appendAddresses( diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt index adc8353252..07e0eb137e 100644 --- a/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt +++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt @@ -6,6 +6,9 @@ import com.tangem.domain.feedback.models.FeedbackEmail import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.feedback.repository.FeedbackRepository import com.tangem.domain.feedback.utils.* +import java.io.File + +private const val BINDER_MAX_SIZE_BYTES = 500_000 // Safe limit under Android's 1MB Binder limit /** * Get email with feedback for support @@ -29,22 +32,30 @@ class SendFeedbackEmailUseCase( address = getAddress(type), subject = emailSubjectResolver.resolve(type), message = createMessage(type), - file = feedbackRepository.getZipLogFile(), + file = getFile(type), ) feedbackRepository.sendEmail(email) } + private suspend fun getFile(type: FeedbackEmailType): File? { + return if (type.isVisaEmail()) { + null + } else { + feedbackRepository.getZipLogFile() + } + } + private fun getAddress(type: FeedbackEmailType): String { return when { - type is FeedbackEmailType.Visa || type.walletMetaInfo?.isVisa == true -> TANGEM_VISA_SUPPORT_EMAIL + type.isVisaEmail() -> TANGEM_VISA_SUPPORT_EMAIL type.walletMetaInfo?.isStart2Coin == true -> START2COIN_SUPPORT_EMAIL else -> TANGEM_SUPPORT_EMAIL } } private suspend fun createMessage(type: FeedbackEmailType): String { - return StringBuilder().apply { + val fullMessage = buildString { val title = emailMessageTitleResolver.resolve(type) append(title) @@ -54,7 +65,25 @@ class SendFeedbackEmailUseCase( val body = emailMessageBodyResolver.resolve(type) append(body) - }.toString() + } + + return truncateMessageIfNeeded(fullMessage) + } + + private fun truncateMessageIfNeeded(message: String): String { + val messageBytes = message.toByteArray(Charsets.UTF_8) + + return if (messageBytes.size > BINDER_MAX_SIZE_BYTES) { + // Find a safe truncation point (avoid cutting in middle of UTF-8 chars) + val truncatedBytes = messageBytes.sliceArray(0 until BINDER_MAX_SIZE_BYTES) + String(truncatedBytes, Charsets.UTF_8) + } else { + message + } + } + + private fun FeedbackEmailType.isVisaEmail(): Boolean { + return this is FeedbackEmailType.Visa || this.walletMetaInfo?.isVisa == true } private fun StringBuilder.appendDisclaimerIfNeeded(type: FeedbackEmailType): StringBuilder { diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt index c8a13a4ef7..1e4ca44bd2 100644 --- a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt +++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt @@ -4,7 +4,6 @@ import com.tangem.domain.feedback.FeedbackDataBuilder import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.feedback.models.WalletMetaInfo import com.tangem.domain.feedback.repository.FeedbackRepository -import com.tangem.domain.visa.model.TangemPayTxHistoryItem import com.tangem.domain.visa.model.VisaTxDetails /** @@ -34,31 +33,39 @@ internal class EmailMessageBodyResolver( -> addPhoneInfoBody() is FeedbackEmailType.Visa.Activation -> addUserRequestBody(type.walletMetaInfo) is FeedbackEmailType.Visa.DirectUserRequest -> addUserRequestBody(type.walletMetaInfo) - is FeedbackEmailType.Visa.FailedIssueCard -> addUserRequestBody(type.walletMetaInfo) is FeedbackEmailType.Visa.Dispute -> addVisaRequestBody(type.walletMetaInfo, type.visaTxDetails) - is FeedbackEmailType.Visa.DisputeV2 -> addTangemPayRequestBody(type.walletMetaInfo, type.item) + is FeedbackEmailType.Visa.FailedIssueCard -> addTangemPayFailedIssuingCardBody(type) + is FeedbackEmailType.Visa.DisputeV2 -> addTangemPayDisputeRequestBody(type) is FeedbackEmailType.Visa.Withdrawal -> addTangemPayWithdrawalRequestBody(type) - is FeedbackEmailType.Visa.FeatureIsBeta -> addTangemPayBetaRequestBody(type.walletMetaInfo) + is FeedbackEmailType.Visa.FeatureIsBeta -> addTangemPayBetaRequestBody(type) } return build() } - private suspend fun FeedbackDataBuilder.addTangemPayRequestBody( - walletMetaInfo: WalletMetaInfo, - item: TangemPayTxHistoryItem, - ) { - addUserRequestBody(walletMetaInfo) + private fun FeedbackDataBuilder.addTangemPayFailedIssuingCardBody(type: FeedbackEmailType.Visa.FailedIssueCard) { + addTangemPayPhoneInfoBody(type) addDelimiter() - addTangemPayTxInfo(item) + type.walletMetaInfo.userWalletId?.let { userWalletId -> + addUserWalletId(userWalletId = userWalletId.stringValue) + } } - private fun FeedbackDataBuilder.addTangemPayBetaRequestBody(walletMetaInfo: WalletMetaInfo) { - addPhoneInfoBody() + private fun FeedbackDataBuilder.addTangemPayDisputeRequestBody(type: FeedbackEmailType.Visa.DisputeV2) { + addTangemPayPhoneInfoBody(type = type) addDelimiter() - walletMetaInfo.userWalletId?.let { userWalletId -> + addTangemPayTxInfo(type.item) + addDelimiter() + type.walletMetaInfo.userWalletId?.let { userWalletId -> + addUserWalletId(userWalletId = userWalletId.stringValue) + } + } + + private fun FeedbackDataBuilder.addTangemPayBetaRequestBody(type: FeedbackEmailType.Visa) { + addTangemPayPhoneInfoBody(type) + addDelimiter() + type.walletMetaInfo?.userWalletId?.let { userWalletId -> addUserWalletId(userWalletId = userWalletId.stringValue) - addDelimiter() } } @@ -122,6 +129,11 @@ internal class EmailMessageBodyResolver( addPhoneInfo(phoneInfo = feedbackRepository.getPhoneInfo()) } + private fun FeedbackDataBuilder.addTangemPayPhoneInfoBody(type: FeedbackEmailType.Visa) { + addPhoneInfo(phoneInfo = feedbackRepository.getPhoneInfo()) + addTangemPayIssueType(type) + } + private suspend fun FeedbackDataBuilder.addTransactionSendingProblemBody(walletMetaInfo: WalletMetaInfo) { addUserWalletMetaInfo(walletMetaInfo) addDelimiter() diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt index ffa4642c46..d227b21dfd 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt @@ -1647,8 +1647,7 @@ internal class SwapModel @Inject constructor( private fun onTangemPaySupportClick(txId: String?) { modelScope.launch { - val metaInfo = getWalletMetaInfoUseCase(userWallet.walletId) - .getOrElse { error("CardInfo must be not null") } + val metaInfo = getWalletMetaInfoUseCase(userWallet.walletId).getOrNull() ?: return@launch val email = FeedbackEmailType.Visa.Withdrawal( walletMetaInfo = metaInfo, providerName = dataState.selectedProvider?.name.orEmpty(), diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryDetailsModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryDetailsModel.kt index 02fd1df5b7..8dae2f4f77 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryDetailsModel.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryDetailsModel.kt @@ -9,8 +9,6 @@ import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.feedback.GetWalletMetaInfoUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.FeedbackEmailType -import com.tangem.domain.models.wallet.requireColdWallet -import com.tangem.domain.wallets.usecase.GetWalletsUseCase import com.tangem.features.tangempay.components.txHistory.TangemPayTxHistoryDetailsComponent import com.tangem.features.tangempay.entity.TangemPayTxHistoryDetailsUM import com.tangem.features.tangempay.model.transformers.TangemPayTxHistoryDetailsConverter @@ -21,10 +19,8 @@ import javax.inject.Inject @Stable @ModelScoped -@Suppress("LongParameterList") internal class TangemPayTxHistoryDetailsModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, - private val getUserWalletsUseCase: GetWalletsUseCase, private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, private val urlOpener: UrlOpener, @@ -66,12 +62,7 @@ internal class TangemPayTxHistoryDetailsModel @Inject constructor( private fun dispute() { modelScope.launch { - val userWalletId = params.userWalletId - val userWallet = getUserWalletsUseCase.invokeSync() - .firstOrNull { it.walletId == userWalletId } ?: return@launch - val walletMetaInfo = getWalletMetaInfoUseCase.invoke( - userWallet.requireColdWallet().scanResponse, - ).getOrNull() ?: return@launch + val walletMetaInfo = getWalletMetaInfoUseCase.invoke(params.userWalletId).getOrNull() ?: return@launch sendFeedbackEmailUseCase.invoke( FeedbackEmailType.Visa.DisputeV2( diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangempayTxDetailsUi.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangempayTxDetailsUi.kt index 4e280d9cb7..c406c83696 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangempayTxDetailsUi.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangempayTxDetailsUi.kt @@ -6,6 +6,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter @@ -74,6 +75,7 @@ internal fun TangemPayTxHistoryDetailsContent(state: TangemPayTxHistoryDetailsUM text = state.transactionSubtitle.resolveReference(), style = TangemTheme.typography.body2, color = TangemTheme.colors.text.tertiary, + textAlign = TextAlign.Center, ) Text( modifier = Modifier.padding(top = 8.dp), @@ -84,7 +86,7 @@ internal fun TangemPayTxHistoryDetailsContent(state: TangemPayTxHistoryDetailsUM state.localTransactionText?.let { localTransaction -> Text( modifier = Modifier.padding(top = 4.dp), - text = localTransaction, + text = localTransaction.orMaskWithStars(state.isBalanceHidden), style = TangemTheme.typography.body2, color = TangemTheme.colors.text.tertiary, ) @@ -207,11 +209,11 @@ private class TangemPayTxHistoryDetailsUMProvider : CollectionPreviewParameterPr dismiss = {}, ), TangemPayTxHistoryDetailsUM( - isBalanceHidden = false, + isBalanceHidden = true, title = stringReference("12 June • 12:40"), iconState = ImageReference.Res(R.drawable.ic_category_24), transactionTitle = stringReference("Starbucks"), - transactionSubtitle = stringReference("Food and drinks"), + transactionSubtitle = stringReference("Food and drinks Food and drinks Food and drinks Food and drinks"), transactionAmount = "-$5.86", transactionAmountColor = themedColor { TangemTheme.colors.text.primary1 }, localTransactionText = "€ 5.36", diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/TangemPayClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/TangemPayClickIntents.kt index 332b9c24af..a844424033 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/TangemPayClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/TangemPayClickIntents.kt @@ -10,11 +10,9 @@ import com.tangem.domain.feedback.GetWalletMetaInfoUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.models.wallet.requireColdWallet import com.tangem.domain.pay.repository.OnboardingRepository import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase -import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController import com.tangem.features.tangempay.TangemPayFeatureToggles import kotlinx.coroutines.launch @@ -41,7 +39,6 @@ internal class TangemPayClickIntentsImplementor @Inject constructor( private val onboardingRepository: OnboardingRepository, private val produceInitialDataTangemPay: ProduceTangemPayInitialDataUseCase, private val getWalletMetainfoUseCase: GetWalletMetaInfoUseCase, - private val getUserWalletUseCase: GetUserWalletUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, private val tangemPayMainScreenCustomerInfoUseCase: TangemPayMainScreenCustomerInfoUseCase, private val uiMessageSender: UiMessageSender, @@ -93,7 +90,7 @@ internal class TangemPayClickIntentsImplementor @Inject constructor( body = resourceReference(R.string.tangempay_failed_to_issue_card_support_description) } secondaryButton { - text = resourceReference(R.string.common_contact_support) + text = resourceReference(R.string.tangempay_go_to_support) onClick { onPaySupportClick() closeBs() @@ -106,10 +103,8 @@ internal class TangemPayClickIntentsImplementor @Inject constructor( override fun onPaySupportClick() { modelScope.launch { - val userWalletId = stateHolder.getSelectedWalletId() - val userWallet = getUserWalletUseCase.invoke(userWalletId).getOrNull() ?: return@launch val cardInfo = getWalletMetainfoUseCase.invoke( - userWallet.requireColdWallet().scanResponse, + userWalletId = stateHolder.getSelectedWalletId(), ).getOrNull() ?: return@launch sendFeedbackEmailUseCase(