diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 9dd3c09886..cd16482c4c 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -482,7 +482,7 @@
Networks
Mostly used
No results
- Earn
+ Staking & Yield mode
Hi support team, I\'ve encountered an error with code: %s
WalletConnect error
You have used a card or ring from another wallet. Tap the card or ring associated with this wallet
@@ -706,7 +706,7 @@
Mana level
To begin tracking your crypto assets and transactions, add tokens
Manage tokens
- Scan QR code to send funds or connect to an app
+ Scan QR code to send funds or connect to an app
To access all the networks you need to scan the card
Scan your card or ring
Enjoy %1$s service fees on swaps via Changelly from February %2$s-%3$s
@@ -741,7 +741,7 @@
APY %s
My portfolio
Market
- Earn with Tangem
+ Staking & Yield mode
To generate addresses for selected networks, you must scan your Tangem Wallet card or ring
To add tokens pull this up or tap the search bar
Swipe up to explore the market
@@ -1054,7 +1054,7 @@
The purchase amount should be no more than %s
The amount to buy must be at least %s
No available providers for this currency
- Quickest Processing
+ Quickest processing
Pay with
Payment method
Available up to %s
@@ -1104,6 +1104,12 @@
Settings
You have not given access to your camera
Camera access denied
+ Requested token is not added to your wallet. Please add it and try again.
+ Token not added
+ Sorry, this QR code could not be recognized.
+ Unrecognized QR Code
+ This network isn\'t supported by any of your added tokens. Add a supported token to send crypto.
+ No supported tokens found
No memo required
%1$s (%2$s) on %3$s network
%1$s on %2$s network
@@ -1249,6 +1255,11 @@
Transaction limitation
Optional
Please align your QR code with the square to scan it. Ensure you scan %s network address.
+ When you use a fixed rate, the amount you receive is locked in at the time of the swap. This protects you from price changes during the transaction.
+ Fixed rate
+ A floating rate means the final amount you receive may change slightly based on market conditions between the time you start and complete the swap.
+ Floating rate
+ Rate is fixed
Recent
Recipient
Not a valid address
@@ -1292,6 +1303,7 @@
Recipient gets %s
Are you sure you want to cancel the conversion? Your previous data will be cleared.
Remove Conversion
+ Something went wrong. Try again.
Send with swap
Transaction sent
Prepare to scan card or ring you want to set up.
@@ -1458,8 +1470,8 @@
The network will charge a token approval fee to verify that you are authorizing the use of your token for the swap.
Exchange more tokens at better rates directly in your wallet.
New Swap Provider Available!
- Looking for something else?\nTry searching or explore another crypto!
- Search for any token, even if it’s not in your list yet.
+ Looking for something else?\nTry searching or explore another crypto!
+ Search for any token, even if it’s not in your list yet.
Use search to find what you need
Feel confident with round-the-clock support to help with any issues
Always Here
diff --git a/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/Bip321PaymentUriParser.kt b/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/Bip321PaymentUriParser.kt
index fc33495e08..0d6ed638f3 100644
--- a/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/Bip321PaymentUriParser.kt
+++ b/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/Bip321PaymentUriParser.kt
@@ -17,11 +17,17 @@ internal class Bip321PaymentUriParser(
val (matchingCoins, withoutScheme) = schemeAndRest
val parsed = QrSentUriParser().parse(withoutScheme)
- ?: return PaymentUriParser.ParseResult.RecognizedButNoMatch
+ ?: return PaymentUriParser.ParseResult.RecognizedError(
+ ClassifiedQrContent.Error.Unrecognized(qrCode),
+ )
val matchingNetworkIds = matchingCoins.map { it.network.id }.toSet()
val matchingCurrencies = allCurrencies.filter { it.network.id in matchingNetworkIds }
- if (matchingCurrencies.isEmpty()) return PaymentUriParser.ParseResult.RecognizedButNoMatch
+ if (matchingCurrencies.isEmpty()) {
+ return PaymentUriParser.ParseResult.RecognizedError(
+ ClassifiedQrContent.Error.UnsupportedNetwork,
+ )
+ }
return PaymentUriParser.ParseResult.Success(
ClassifiedQrContent.PaymentUri(
diff --git a/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/Eip681PaymentUriParser.kt b/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/Eip681PaymentUriParser.kt
index 3853849fcd..5a47f9b717 100644
--- a/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/Eip681PaymentUriParser.kt
+++ b/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/Eip681PaymentUriParser.kt
@@ -23,10 +23,17 @@ internal class Eip681PaymentUriParser(
val matchingCoins = findMatchingCoins(parsed.chainId, coins)
if (matchingCoins.isEmpty()) {
- return PaymentUriParser.ParseResult.RecognizedButNoMatch
+ return PaymentUriParser.ParseResult.RecognizedError(
+ ClassifiedQrContent.Error.UnsupportedNetwork,
+ )
}
val result = if (parsed.functionName == FUNCTION_TRANSFER) {
+ if (PARAM_ADDRESS !in parsed.params) {
+ return PaymentUriParser.ParseResult.RecognizedError(
+ ClassifiedQrContent.Error.Unrecognized(qrCode),
+ )
+ }
resolveErc20Transfer(parsed, matchingCoins, allCurrencies)
} else {
resolveNativeTransfer(parsed, matchingCoins, allCurrencies)
@@ -34,7 +41,9 @@ internal class Eip681PaymentUriParser(
return if (result != null) {
PaymentUriParser.ParseResult.Success(result)
} else {
- PaymentUriParser.ParseResult.RecognizedButNoMatch
+ PaymentUriParser.ParseResult.RecognizedError(
+ ClassifiedQrContent.Error.UnsupportedNetwork,
+ )
}
}
diff --git a/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/PaymentUriParser.kt b/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/PaymentUriParser.kt
index 8ade342f92..e7a64b8740 100644
--- a/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/PaymentUriParser.kt
+++ b/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/PaymentUriParser.kt
@@ -11,8 +11,8 @@ internal interface PaymentUriParser {
/** URI format not recognized by this parser. */
data object NotRecognized : ParseResult()
- /** URI format recognized but no matching currencies found. */
- data object RecognizedButNoMatch : ParseResult()
+ /** URI format recognized but resulted in an error. */
+ data class RecognizedError(val error: ClassifiedQrContent.Error) : ParseResult()
/** Successfully parsed with matching currencies. */
data class Success(val content: ClassifiedQrContent.PaymentUri) : ParseResult()
diff --git a/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/QrContentClassifierParser.kt b/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/QrContentClassifierParser.kt
index 6d970e3ec4..ef468d89b0 100644
--- a/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/QrContentClassifierParser.kt
+++ b/data/qr-scanning/src/main/java/com/tangem/data/qrscanning/parser/QrContentClassifierParser.kt
@@ -1,5 +1,6 @@
package com.tangem.data.qrscanning.parser
+import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.utils.toBlockchain
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
@@ -25,7 +26,7 @@ internal class QrContentClassifierParser(
when (val paymentUriResult = tryParsePaymentUri(qrCode, uniqueCoins, userCurrencies)) {
is PaymentUriParser.ParseResult.Success -> return paymentUriResult.content
- is PaymentUriParser.ParseResult.RecognizedButNoMatch -> return ClassifiedQrContent.Unknown(qrCode)
+ is PaymentUriParser.ParseResult.RecognizedError -> return paymentUriResult.error
is PaymentUriParser.ParseResult.NotRecognized -> Unit
}
@@ -35,13 +36,18 @@ internal class QrContentClassifierParser(
if (matchingNetworkIds.isNotEmpty()) {
val matchingCurrencies = userCurrencies.filter { it.network.id in matchingNetworkIds }
+
return ClassifiedQrContent.PlainAddress(
address = qrCode,
matchingCurrencies = matchingCurrencies,
)
}
- return ClassifiedQrContent.Unknown(qrCode)
+ if (blockchainDataProvider.isSupportedAddress(qrCode)) {
+ return ClassifiedQrContent.Error.UnsupportedNetwork
+ }
+
+ return ClassifiedQrContent.Error.Unrecognized(qrCode)
}
private fun tryParsePaymentUri(
@@ -70,6 +76,7 @@ internal class QrContentClassifierParser(
fun getShareSchemes(network: Network): List
fun validateAddress(network: Network, address: String): Boolean
fun getChainId(network: Network): Long?
+ fun isSupportedAddress(address: String): Boolean
}
internal class DefaultBlockchainDataProvider : BlockchainDataProvider {
@@ -84,6 +91,14 @@ internal class QrContentClassifierParser(
override fun getChainId(network: Network): Long? {
return runCatching { network.toBlockchain().getChainId()?.toLong() }.getOrNull()
}
+
+ override fun isSupportedAddress(address: String): Boolean {
+ return Blockchain.entries
+ .filter { !it.isTestnet() }
+ .any { blockchain ->
+ runCatching { blockchain.validateAddress(address) }.getOrDefault(false)
+ }
+ }
}
private companion object {
diff --git a/data/qr-scanning/src/test/java/com/tangem/data/qrscanning/Eip681PaymentUriParserTest.kt b/data/qr-scanning/src/test/java/com/tangem/data/qrscanning/Eip681PaymentUriParserTest.kt
index f78e4d22da..7b0662377e 100644
--- a/data/qr-scanning/src/test/java/com/tangem/data/qrscanning/Eip681PaymentUriParserTest.kt
+++ b/data/qr-scanning/src/test/java/com/tangem/data/qrscanning/Eip681PaymentUriParserTest.kt
@@ -142,7 +142,7 @@ internal class Eip681PaymentUriParserTest {
}
@Test
- fun `ERC-20 transfer with unknown token returns RecognizedButNoMatch`() {
+ fun `ERC-20 transfer with unknown token returns UnsupportedNetwork error`() {
every { blockchainDataProvider.getChainId(ethereumCoin.network) } returns 1L
val result = parser.parse(
@@ -151,11 +151,13 @@ internal class Eip681PaymentUriParserTest {
allCurrencies = listOf(ethereumCoin),
)
- assertThat(result).isInstanceOf(PaymentUriParser.ParseResult.RecognizedButNoMatch::class.java)
+ assertThat(result).isInstanceOf(PaymentUriParser.ParseResult.RecognizedError::class.java)
+ val error = (result as PaymentUriParser.ParseResult.RecognizedError).error
+ assertThat(error).isInstanceOf(ClassifiedQrContent.Error.UnsupportedNetwork::class.java)
}
@Test
- fun `ERC-20 transfer without address param returns RecognizedButNoMatch`() {
+ fun `ERC-20 transfer without address param returns Unrecognized error`() {
every { blockchainDataProvider.getChainId(ethereumCoin.network) } returns 1L
val usdcToken = buildToken("ethereum", "USDC", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")
@@ -166,7 +168,9 @@ internal class Eip681PaymentUriParserTest {
allCurrencies = listOf(ethereumCoin, usdcToken),
)
- assertThat(result).isInstanceOf(PaymentUriParser.ParseResult.RecognizedButNoMatch::class.java)
+ assertThat(result).isInstanceOf(PaymentUriParser.ParseResult.RecognizedError::class.java)
+ val error = (result as PaymentUriParser.ParseResult.RecognizedError).error
+ assertThat(error).isInstanceOf(ClassifiedQrContent.Error.Unrecognized::class.java)
}
// endregion
@@ -192,7 +196,7 @@ internal class Eip681PaymentUriParserTest {
// region Chain ID matching
@Test
- fun `chain_id mismatch returns RecognizedButNoMatch`() {
+ fun `chain_id mismatch returns UnsupportedNetwork error`() {
every { blockchainDataProvider.getChainId(ethereumCoin.network) } returns 1L
val result = parser.parse(
@@ -201,7 +205,9 @@ internal class Eip681PaymentUriParserTest {
allCurrencies = listOf(ethereumCoin),
)
- assertThat(result).isInstanceOf(PaymentUriParser.ParseResult.RecognizedButNoMatch::class.java)
+ assertThat(result).isInstanceOf(PaymentUriParser.ParseResult.RecognizedError::class.java)
+ val error = (result as PaymentUriParser.ParseResult.RecognizedError).error
+ assertThat(error).isInstanceOf(ClassifiedQrContent.Error.UnsupportedNetwork::class.java)
}
@Test
diff --git a/data/qr-scanning/src/test/java/com/tangem/data/qrscanning/QrContentClassifierTest.kt b/data/qr-scanning/src/test/java/com/tangem/data/qrscanning/QrContentClassifierTest.kt
index c8b289207f..86075b2a10 100644
--- a/data/qr-scanning/src/test/java/com/tangem/data/qrscanning/QrContentClassifierTest.kt
+++ b/data/qr-scanning/src/test/java/com/tangem/data/qrscanning/QrContentClassifierTest.kt
@@ -17,6 +17,7 @@ internal class QrContentClassifierTest {
every { getShareSchemes(any()) } returns emptyList()
every { validateAddress(any(), any()) } returns false
every { getChainId(any()) } returns null
+ every { isSupportedAddress(any()) } returns false
}
private val paymentUriParser = mockk {
every { parse(any(), any(), any()) } returns PaymentUriParser.ParseResult.NotRecognized
@@ -63,7 +64,7 @@ internal class QrContentClassifierTest {
val result = classifier.parse(url, listOf(bitcoinCoin))
- assertThat(result).isInstanceOf(ClassifiedQrContent.Unknown::class.java)
+ assertThat(result).isInstanceOf(ClassifiedQrContent.Error.Unrecognized::class.java)
}
@Test
@@ -72,7 +73,7 @@ internal class QrContentClassifierTest {
val result = classifier.parse(url, listOf(bitcoinCoin))
- assertThat(result).isInstanceOf(ClassifiedQrContent.Unknown::class.java)
+ assertThat(result).isInstanceOf(ClassifiedQrContent.Error.Unrecognized::class.java)
}
// endregion
@@ -162,22 +163,22 @@ internal class QrContentClassifierTest {
fun `Random string returns Unknown`() {
val result = classifier.parse("hello world", listOf(bitcoinCoin, ethereumCoin))
- assertThat(result).isInstanceOf(ClassifiedQrContent.Unknown::class.java)
- assertThat((result as ClassifiedQrContent.Unknown).raw).isEqualTo("hello world")
+ assertThat(result).isInstanceOf(ClassifiedQrContent.Error.Unrecognized::class.java)
+ assertThat((result as ClassifiedQrContent.Error.Unrecognized).raw).isEqualTo("hello world")
}
@Test
fun `Empty string returns Unknown`() {
val result = classifier.parse("", listOf(bitcoinCoin))
- assertThat(result).isInstanceOf(ClassifiedQrContent.Unknown::class.java)
+ assertThat(result).isInstanceOf(ClassifiedQrContent.Error.Unrecognized::class.java)
}
@Test
fun `Empty currencies list returns Unknown`() {
val result = classifier.parse("0x1234567890abcdef1234567890abcdef12345678", emptyList())
- assertThat(result).isInstanceOf(ClassifiedQrContent.Unknown::class.java)
+ assertThat(result).isInstanceOf(ClassifiedQrContent.Error.Unrecognized::class.java)
}
@Test
@@ -186,7 +187,7 @@ internal class QrContentClassifierTest {
val result = classifier.parse("0x1234", listOf(token))
- assertThat(result).isInstanceOf(ClassifiedQrContent.Unknown::class.java)
+ assertThat(result).isInstanceOf(ClassifiedQrContent.Error.Unrecognized::class.java)
}
// endregion
diff --git a/domain/qr-scanning/models/src/main/java/com/tangem/domain/qrscanning/models/ClassifiedQrContent.kt b/domain/qr-scanning/models/src/main/java/com/tangem/domain/qrscanning/models/ClassifiedQrContent.kt
index dab8a60259..da41ec31fa 100644
--- a/domain/qr-scanning/models/src/main/java/com/tangem/domain/qrscanning/models/ClassifiedQrContent.kt
+++ b/domain/qr-scanning/models/src/main/java/com/tangem/domain/qrscanning/models/ClassifiedQrContent.kt
@@ -19,5 +19,12 @@ sealed class ClassifiedQrContent {
val matchingCurrencies: List,
) : ClassifiedQrContent()
- data class Unknown(val raw: String) : ClassifiedQrContent()
+ sealed class Error : ClassifiedQrContent() {
+
+ /** QR code not recognized by any parser */
+ data class Unrecognized(val raw: String) : Error()
+
+ /** Network or token recognized but not available in user's wallet */
+ data object UnsupportedNetwork : Error()
+ }
}
\ No newline at end of file
diff --git a/domain/qr-scanning/models/src/main/java/com/tangem/domain/qrscanning/models/QrSendTarget.kt b/domain/qr-scanning/models/src/main/java/com/tangem/domain/qrscanning/models/QrSendTarget.kt
index d0443ffdd7..7220a7ef95 100644
--- a/domain/qr-scanning/models/src/main/java/com/tangem/domain/qrscanning/models/QrSendTarget.kt
+++ b/domain/qr-scanning/models/src/main/java/com/tangem/domain/qrscanning/models/QrSendTarget.kt
@@ -41,5 +41,5 @@ sealed class QrSendTarget {
data class WalletConnect(val uri: String) : QrSendTarget()
- data class Unknown(val raw: String) : QrSendTarget()
+ data class Error(val error: ClassifiedQrContent.Error) : QrSendTarget()
}
\ No newline at end of file
diff --git a/domain/qr-scanning/src/main/java/com/tangem/domain/qrscanning/usecases/ResolveQrSendTargetsUseCase.kt b/domain/qr-scanning/src/main/java/com/tangem/domain/qrscanning/usecases/ResolveQrSendTargetsUseCase.kt
index bfa7169dac..a33e20ec2d 100644
--- a/domain/qr-scanning/src/main/java/com/tangem/domain/qrscanning/usecases/ResolveQrSendTargetsUseCase.kt
+++ b/domain/qr-scanning/src/main/java/com/tangem/domain/qrscanning/usecases/ResolveQrSendTargetsUseCase.kt
@@ -52,7 +52,7 @@ class ResolveQrSendTargetsUseCase(
private fun resolve(classified: ClassifiedQrContent, portfolioIndex: PortfolioIndex): QrSendTarget {
return when (classified) {
is ClassifiedQrContent.WalletConnect -> QrSendTarget.WalletConnect(classified.uri)
- is ClassifiedQrContent.Unknown -> QrSendTarget.Unknown(classified.raw)
+ is ClassifiedQrContent.Error -> QrSendTarget.Error(classified)
is ClassifiedQrContent.PlainAddress -> resolveAddressTarget(
address = classified.address,
amount = null,
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt
index 44c6eb55fc..5340b32bc2 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt
@@ -11,6 +11,7 @@ import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
import com.tangem.core.analytics.utils.TrackingContextProxy
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
+import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.domain.account.supplier.SingleAccountListSupplier
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
@@ -26,6 +27,7 @@ import com.tangem.domain.notifications.repository.NotificationsRepository
import com.tangem.domain.qrscanning.models.QrResultSource
import com.tangem.domain.qrscanning.models.SourceType
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
+import com.tangem.domain.qrscanning.models.ClassifiedQrContent
import com.tangem.domain.qrscanning.models.QrSendTarget
import com.tangem.domain.walletconnect.WcPairService
import com.tangem.domain.walletconnect.model.WcPairRequest
@@ -47,6 +49,7 @@ import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
import com.tangem.feature.wallet.presentation.wallet.domain.WalletNameMigrationUseCase
import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContentLoader
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
+import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertUM
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent.DemonstrateWalletsScrollPreview.Direction
@@ -115,6 +118,7 @@ internal class WalletModel @Inject constructor(
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
private val wcPairService: WcPairService,
private val resolveQrSendTargetsUseCase: ResolveQrSendTargetsUseCase,
+ private val uiMessageSender: UiMessageSender,
val screenLifecycleProvider: ScreenLifecycleProvider,
val innerWalletRouter: InnerWalletRouter,
) : Model() {
@@ -778,8 +782,17 @@ internal class WalletModel @Inject constructor(
is QrSendTarget.Multiple -> {
innerWalletRouter.openNetworkSelectionBottomSheet(target)
}
- is QrSendTarget.Unknown -> {
- // TODO: [REDACTED_TASK_KEY] Error handling for unsupported and invalid QR codes
+ is QrSendTarget.Error -> handleQrError(target.error)
+ }
+ }
+
+ private fun handleQrError(error: ClassifiedQrContent.Error) {
+ when (error) {
+ is ClassifiedQrContent.Error.Unrecognized -> {
+ uiMessageSender.send(WalletAlertUM.qrCodeUnrecognized())
+ }
+ is ClassifiedQrContent.Error.UnsupportedNetwork -> {
+ uiMessageSender.send(WalletAlertUM.qrCodeUnsupportedNetwork())
}
}
}
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletAlertUM.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletAlertUM.kt
index a0fe35468c..665fcfdafd 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletAlertUM.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletAlertUM.kt
@@ -80,6 +80,20 @@ internal object WalletAlertUM {
)
}
+ fun qrCodeUnrecognized(): DialogMessage {
+ return DialogMessage(
+ title = resourceReference(R.string.qr_scanner_error_unrecognized_title),
+ message = resourceReference(R.string.qr_scanner_error_unrecognized_message),
+ )
+ }
+
+ fun qrCodeUnsupportedNetwork(): DialogMessage {
+ return DialogMessage(
+ title = resourceReference(R.string.qr_scanner_error_token_not_added_title),
+ message = resourceReference(R.string.qr_scanner_error_token_not_added_message),
+ )
+ }
+
fun confirmExpressStatusHide(onConfirmClick: () -> Unit): DialogMessage {
return DialogMessage(
title = resourceReference(R.string.express_status_hide_dialog_title),