diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 570f9e96e3..1ff2af8354 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -9,17 +9,28 @@ plugins {
id("configuration")
}
-//conflict of dependencies when adding WalletConnectV2.0 library
-configurations {
- all {
- exclude(group = "org.bouncycastle", module = "bcprov-jdk15to18")
- resolutionStrategy {
- force("org.bouncycastle:bcpkix-jdk15on:1.70")
+configurations.all {
+ exclude(group = "org.bouncycastle", module = "bcprov-jdk15to18")
+ exclude(group = "com.github.komputing.kethereum")
+
+ resolutionStrategy {
+ dependencySubstitution {
+ substitute(module("com.facebook.react:react-native"))
+ .using(module("com.facebook.react:react-android:0.72.4"))
+
+ substitute(module("com.facebook.react:hermes-engine"))
+ .using(module("com.facebook.react:hermes-android:0.72.4"))
}
- exclude(group = "com.github.komputing.kethereum")
+
+ force(
+ "org.bouncycastle:bcpkix-jdk15on:1.70",
+ "com.facebook.react:react-android:0.72.4",
+ "com.facebook.react:hermes-android:0.72.4",
+ )
}
}
+
dependencies {
implementation(files("libs/walletconnect-1.5.6.aar"))
implementation(project(":domain:legacy"))
@@ -159,6 +170,10 @@ dependencies {
implementation(deps.walletConnectCore)
implementation(deps.walletConnectWeb3)
implementation(deps.prettyLogger)
+ implementation("com.facebook.react:react-android:0.72.4")
+ implementation(deps.sprClient) {
+ exclude(group = "com.github.stephenc.jcip")
+ }
/** Testing libraries */
testImplementation(deps.test.junit)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 53d4be3c7f..c1b1d65718 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,6 +12,16 @@
+
+
+
+
+
@@ -39,7 +49,7 @@
android:extractNativeLibs="true"
android:supportsRtl="true"
tools:ignore="GoogleAppIndexingWarning"
- tools:replace="android:allowBackup, android:fullBackupContent">
+ tools:replace="android:allowBackup, android:fullBackupContent, android:label">
-
-
diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt
index cfd38560ca..8c4091a21f 100644
--- a/app/src/main/java/com/tangem/tap/TapApplication.kt
+++ b/app/src/main/java/com/tangem/tap/TapApplication.kt
@@ -336,7 +336,7 @@ class TapApplication : Application(), ImageLoaderFactory {
val feedbackManager = FeedbackManager(
infoHolder = additionalFeedbackInfo,
logCollector = tangemLogCollector,
- chatManager = ChatManager(preferencesStorage, foregroundActivityObserver, store),
+ chatManager = ChatManager(preferencesStorage, foregroundActivityObserver),
)
store.dispatch(GlobalAction.SetFeedbackManager(feedbackManager))
}
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 0db51098a3..6db15ac882 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,6 +45,7 @@ class CardContextInterceptor(
ProductType.Note -> "Note"
ProductType.Twins -> "Twin"
ProductType.Wallet -> "Wallet"
+ ProductType.Wallet2 -> "Wallet 2.0"
ProductType.Start2Coin -> "Start2Coin"
else -> if (DemoHelper.isDemoCard(scanResponse)) {
if (DemoHelper.isTestDemoCard(scanResponse)) {
diff --git a/app/src/main/java/com/tangem/tap/common/chat/ChatManager.kt b/app/src/main/java/com/tangem/tap/common/chat/ChatManager.kt
index 56ded693ad..693113b27a 100644
--- a/app/src/main/java/com/tangem/tap/common/chat/ChatManager.kt
+++ b/app/src/main/java/com/tangem/tap/common/chat/ChatManager.kt
@@ -2,37 +2,31 @@ package com.tangem.tap.common.chat
import android.content.Context
import android.os.Build
+import com.tangem.data.source.preferences.PreferencesDataSource
import com.tangem.datasource.config.models.ChatConfig
import com.tangem.datasource.config.models.SprinklrConfig
import com.tangem.datasource.config.models.ZendeskConfig
-import com.tangem.data.source.preferences.PreferencesDataSource
import com.tangem.tap.ForegroundActivityObserver
import com.tangem.tap.common.chat.opener.ChatOpener
import com.tangem.tap.common.chat.opener.implementation.SprinklrChatOpener
import com.tangem.tap.common.chat.opener.implementation.ZendeskChatOpener
-import com.tangem.tap.common.redux.AppState
-import org.rekotlin.Store
import java.io.File
class ChatManager(
private val preferencesStorage: PreferencesDataSource,
private val foregroundActivityObserver: ForegroundActivityObserver,
- private val store: Store,
) {
private val openers = mutableMapOf()
fun open(config: ChatConfig, createLogsFile: (Context) -> File?, createFeedbackFile: (Context) -> File?) {
val opener = openers.getOrPut(config) {
when (config) {
- is SprinklrConfig -> SprinklrChatOpener(getSprinklrUserId(), config, store, foregroundActivityObserver)
+ is SprinklrConfig -> SprinklrChatOpener(config, foregroundActivityObserver)
is ZendeskConfig -> ZendeskChatOpener(getZendeskUserId(), config, foregroundActivityObserver)
}
}
- opener.open(
- createFeedbackFile = createFeedbackFile,
- createLogsFile = createLogsFile,
- )
+ opener.open(createFeedbackFile, createLogsFile)
}
private fun getZendeskUserId(): String {
@@ -40,18 +34,6 @@ class ChatManager(
preferencesStorage.zendeskFirstLaunchTime = System.currentTimeMillis()
}
- return getChatUserId(preferencesStorage.zendeskFirstLaunchTime!!)
- }
-
- private fun getSprinklrUserId(): String {
- if (preferencesStorage.sprinklrFirstLaunchTime == null) {
- preferencesStorage.sprinklrFirstLaunchTime = System.currentTimeMillis()
- }
-
- return getChatUserId(preferencesStorage.sprinklrFirstLaunchTime!!)
- }
-
- private fun getChatUserId(firstLaunchTimeMillis: Long): String {
- return "${firstLaunchTimeMillis}${Build.MODEL}".hashCode().toString()
+ return "${preferencesStorage.zendeskFirstLaunchTime}${Build.MODEL}".hashCode().toString()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/chat/opener/implementation/SprinklrChatOpener.kt b/app/src/main/java/com/tangem/tap/common/chat/opener/implementation/SprinklrChatOpener.kt
index f8936d6abd..0fcb2a4cf2 100644
--- a/app/src/main/java/com/tangem/tap/common/chat/opener/implementation/SprinklrChatOpener.kt
+++ b/app/src/main/java/com/tangem/tap/common/chat/opener/implementation/SprinklrChatOpener.kt
@@ -1,28 +1,57 @@
package com.tangem.tap.common.chat.opener.implementation
+import android.annotation.SuppressLint
+import android.app.Application
import android.content.Context
-import android.content.Intent
+import android.provider.Settings
+import com.spr.messengerclient.config.SPRMessenger
+import com.spr.messengerclient.config.bean.SPRMessengerConfig
+import com.tangem.common.extensions.guard
import com.tangem.datasource.config.models.SprinklrConfig
import com.tangem.tap.ForegroundActivityObserver
import com.tangem.tap.common.chat.opener.ChatOpener
-import com.tangem.tap.common.redux.AppState
-import com.tangem.tap.features.sprinklr.redux.SprinklrAction
-import com.tangem.tap.features.sprinklr.ui.SprinklrActivity
-import com.tangem.tap.withForegroundActivity
-import org.rekotlin.Store
+import timber.log.Timber
import java.io.File
+import java.util.Locale
internal class SprinklrChatOpener(
- private val userId: String,
private val config: SprinklrConfig,
- private val store: Store,
private val foregroundActivityObserver: ForegroundActivityObserver,
) : ChatOpener {
+
override fun open(createFeedbackFile: (Context) -> File?, createLogsFile: (Context) -> File?) {
- store.dispatch(SprinklrAction.Init(userId, config))
- foregroundActivityObserver.withForegroundActivity { activity ->
- val intent = Intent(activity, SprinklrActivity::class.java)
- activity.startActivity(intent)
+ val messenger = SPRMessenger.shared()
+
+ if (messenger.config == null) {
+ initSprConfig(messenger)
+ }
+
+ messenger.startApplication()
+ }
+
+ private fun initSprConfig(messenger: SPRMessenger) {
+ val application = foregroundActivityObserver.foregroundActivity?.application.guard {
+ Timber.e("The SPR chat cannot be opened because there are no activities in foreground")
+ return
+ }
+
+ messenger.takeOff(application, createSprConfig(application, config))
+ }
+
+ @SuppressLint("HardwareIds")
+ private fun createSprConfig(application: Application, config: SprinklrConfig): SPRMessengerConfig {
+ return SPRMessengerConfig().apply {
+ appId = config.appId
+ appKey = CHAT_APP_KEY
+ deviceId = Settings.Secure.getString(application.contentResolver, Settings.Secure.ANDROID_ID)
+ environment = config.environment
+ skin = CHAT_SKIN
+ locale = Locale.getDefault().language
}
}
+
+ private companion object {
+ const val CHAT_APP_KEY = "com.sprinklr.messenger.release"
+ const val CHAT_SKIN = "MODERN"
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt
index 7210599e41..8175888c08 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt
@@ -14,7 +14,6 @@ import com.tangem.tap.features.saveWallet.redux.SaveWalletReducer
import com.tangem.tap.features.send.redux.reducers.SendScreenReducer
import com.tangem.tap.features.shop.redux.ShopReducer
import com.tangem.tap.features.signin.redux.SignInReducer
-import com.tangem.tap.features.sprinklr.redux.SprinklrReducer
import com.tangem.tap.features.tokens.legacy.redux.TokensReducer
import com.tangem.tap.features.wallet.redux.reducers.WalletReducer
import com.tangem.tap.features.walletSelector.redux.WalletSelectorReducer
@@ -45,7 +44,6 @@ fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder)
welcomeState = WelcomeReducer.reduce(action, state),
saveWalletState = SaveWalletReducer.reduce(action, state),
walletSelectorState = WalletSelectorReducer.reduce(action, state),
- sprinklrState = SprinklrReducer.reduce(action, state),
signInState = SignInReducer.reduce(action, state),
daggerGraphState = DaggerGraphReducer.reduce(action, state),
)
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 71be2aa020..19248b08b9 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
@@ -32,8 +32,6 @@ import com.tangem.tap.features.shop.redux.ShopMiddleware
import com.tangem.tap.features.shop.redux.ShopState
import com.tangem.tap.features.signin.redux.SignInMiddleware
import com.tangem.tap.features.signin.redux.SignInState
-import com.tangem.tap.features.sprinklr.redux.SprinklrMiddleware
-import com.tangem.tap.features.sprinklr.redux.SprinklrState
import com.tangem.tap.features.tokens.legacy.redux.TokensMiddleware
import com.tangem.tap.features.tokens.legacy.redux.TokensState
import com.tangem.tap.features.wallet.redux.WalletState
@@ -66,7 +64,6 @@ data class AppState(
val welcomeState: WelcomeState = WelcomeState(),
val saveWalletState: SaveWalletState = SaveWalletState(),
val walletSelectorState: WalletSelectorState = WalletSelectorState(),
- val sprinklrState: SprinklrState = SprinklrState(),
val signInState: SignInState = SignInState(),
val daggerGraphState: DaggerGraphState = DaggerGraphState(),
) : StateType {
@@ -108,7 +105,6 @@ data class AppState(
WalletSelectorMiddleware().middleware,
LockUserWalletsTimerMiddleware().middleware,
AccessCodeRequestPolicyMiddleware().middleware,
- SprinklrMiddleware().middleware,
SignInMiddleware.middleware,
DaggerGraphMiddleware.daggerGraphMiddleware,
)
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 287b5d35f1..176841c442 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
@@ -100,10 +100,10 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di
}
// if config not set -> try to get it based on a scanResponse.productType
- val unsafeChatConfig = action.chatConfig ?: config.zendesk
+ val unsafeChatConfig = action.chatConfig ?: config.sprinklr
val chatConfig = unsafeChatConfig.guard {
- store.dispatchDebugErrorNotification("ZendeskConfig not initialized")
+ store.dispatchDebugErrorNotification("The chat config is not initialized")
return
}
feedbackManager.openChat(chatConfig, action.feedbackData)
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 31a7a1ade4..b587dee326 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
@@ -216,7 +216,7 @@ private class ScanWalletProcessor(
session: CardSession,
callback: (result: CompletionResult) -> Unit,
) {
- val productType = ProductType.Wallet
+ val productType = getWalletProductType(card)
val config = CardConfig.createConfig(card)
scope.launch {
val scanResponse = ScanResponse(
@@ -280,6 +280,14 @@ private class ScanWalletProcessor(
return blockchainsToDerive.distinct()
}
+ private fun getWalletProductType(card: CardDTO): ProductType {
+ return if (card.firmwareVersion >= FirmwareVersion.Ed25519Slip0010Available) {
+ ProductType.Wallet2
+ } else {
+ ProductType.Wallet
+ }
+ }
+
private fun getDefaultBlockchains(
derivationStyleProvider: DerivationStyleProvider,
): MutableList {
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 baf5ed2fcf..68a4bb6df8 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
@@ -52,7 +52,9 @@ object OnboardingHelper {
fun whereToNavigate(scanResponse: ScanResponse): AppScreen {
return when (scanResponse.productType) {
ProductType.Note -> AppScreen.OnboardingNote
- ProductType.Wallet -> if (scanResponse.card.settings.isBackupAllowed) {
+ ProductType.Wallet,
+ ProductType.Wallet2,
+ -> if (scanResponse.card.settings.isBackupAllowed) {
AppScreen.OnboardingWallet
} else {
AppScreen.OnboardingOther
diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrAction.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrAction.kt
deleted file mode 100644
index b781ee102f..0000000000
--- a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrAction.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.tangem.tap.features.sprinklr.redux
-
-import com.tangem.datasource.config.models.SprinklrConfig
-import org.rekotlin.Action
-
-sealed interface SprinklrAction : Action {
- data class Init(val userId: String, val config: SprinklrConfig) : SprinklrAction
- data class UpdateUrl(val url: String) : SprinklrAction
- data class UpdateSprinklrDomains(val domains: List) : SprinklrAction
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrMiddleware.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrMiddleware.kt
deleted file mode 100644
index 922e3a2e67..0000000000
--- a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrMiddleware.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.tangem.tap.features.sprinklr.redux
-
-import com.tangem.datasource.config.models.SprinklrConfig
-import com.tangem.tap.common.extensions.dispatchOnMain
-import com.tangem.tap.common.redux.AppState
-import com.tangem.tap.features.sprinklr.redux.model.SprinklrUrl
-import com.tangem.tap.store
-import org.rekotlin.Middleware
-
-internal class SprinklrMiddleware {
- val middleware: Middleware = { _, appStateProvider ->
- { next ->
- { action ->
- val appState = appStateProvider()
- if (action is SprinklrAction && appState != null) {
- handleAction(action)
- }
- next(action)
- }
- }
- }
-
- private fun handleAction(action: SprinklrAction) {
- when (action) {
- is SprinklrAction.Init -> updateUrl(action.userId, action.config)
- is SprinklrAction.UpdateUrl,
- is SprinklrAction.UpdateSprinklrDomains,
- -> Unit
- }
- }
-
- private fun updateUrl(userId: String, config: SprinklrConfig) {
- updateSprinklrDomains(config.baseUrl)
- val url = SprinklrUrl.Prod(userId, config.baseUrl, config.appId).url
- store.dispatchOnMain(SprinklrAction.UpdateUrl(url))
- }
-
- private fun updateSprinklrDomains(baseUrl: String) {
- val domains = listOf(baseUrl, SprinklrUrl.Static.url)
- store.dispatchOnMain(SprinklrAction.UpdateSprinklrDomains(domains))
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrReducer.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrReducer.kt
deleted file mode 100644
index a27d16d2db..0000000000
--- a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrReducer.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.tangem.tap.features.sprinklr.redux
-
-import com.tangem.tap.common.redux.AppState
-import org.rekotlin.Action
-
-internal object SprinklrReducer {
- fun reduce(action: Action, state: AppState): SprinklrState {
- return if (action is SprinklrAction) {
- internalReduce(action, state.sprinklrState)
- } else {
- state.sprinklrState
- }
- }
-
- private fun internalReduce(action: SprinklrAction, state: SprinklrState): SprinklrState {
- return when (action) {
- is SprinklrAction.Init -> state
- is SprinklrAction.UpdateUrl -> state.copy(url = action.url)
- is SprinklrAction.UpdateSprinklrDomains -> state.copy(sprinklrDomains = action.domains)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrState.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrState.kt
deleted file mode 100644
index 12ba5b8672..0000000000
--- a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrState.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.tangem.tap.features.sprinklr.redux
-
-data class SprinklrState(
- val url: String = "",
- val sprinklrDomains: List = emptyList(),
-)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/model/SprinklrUrl.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/model/SprinklrUrl.kt
deleted file mode 100644
index 2d1eb1be87..0000000000
--- a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/model/SprinklrUrl.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.tangem.tap.features.sprinklr.redux.model
-
-internal sealed class SprinklrUrl {
- abstract val url: String
-
- class Prod(userId: String, baseUrl: String, appId: String) : SprinklrUrl() {
- private val locale = java.util.Locale.getDefault().language
-
- override val url: String = "$baseUrl/page" +
- "?appId=$appId" +
- "&device=$Device" +
- "&enableClose=$CloseEnabled" +
- "&zoom=$ZoomEnabled" +
- "&locale=$locale" +
- "&user_id=$userId"
-
- companion object {
- private const val Device = "MOBILE"
- private const val CloseEnabled = true
- private const val ZoomEnabled = false
- }
- }
-
- object Static : SprinklrUrl() {
- override val url: String = "live-chat-static.sprinklr.com"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrActivity.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrActivity.kt
deleted file mode 100644
index 7ddbf49c68..0000000000
--- a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrActivity.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.tangem.tap.features.sprinklr.ui
-
-import android.os.Bundle
-import androidx.activity.compose.BackHandler
-import androidx.activity.viewModels
-import androidx.compose.foundation.layout.imePadding
-import androidx.compose.foundation.layout.systemBarsPadding
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.ui.Modifier
-import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.tangem.core.analytics.Analytics
-import com.tangem.core.ui.components.SystemBarsEffect
-import com.tangem.core.ui.res.TangemTheme
-import com.tangem.core.ui.screen.ComposeActivity
-import com.tangem.core.ui.theme.AppThemeModeHolder
-import com.tangem.tap.common.analytics.events.Chat
-import dagger.hilt.android.AndroidEntryPoint
-import javax.inject.Inject
-
-@AndroidEntryPoint
-internal class SprinklrActivity : ComposeActivity() {
-
- @Inject
- override lateinit var appThemeModeHolder: AppThemeModeHolder
-
- private val viewModel by viewModels()
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- Analytics.send(Chat.ScreenOpened())
- viewModel.setNavigateBackCallback {
- this.finish()
- }
- }
-
- @Composable
- override fun ScreenContent(modifier: Modifier) {
- val state by viewModel.state.collectAsStateWithLifecycle()
-
- val systemBarsColor = TangemTheme.colors.background.primary
- SystemBarsEffect {
- setSystemBarsColor(systemBarsColor)
- }
-
- BackHandler(onBack = state.onNavigateBack)
- SprinklrScreenContent(
- modifier = modifier
- .systemBarsPadding()
- .imePadding(),
- state = state,
- )
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenContent.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenContent.kt
deleted file mode 100644
index 5277ba0cea..0000000000
--- a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenContent.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.tangem.tap.features.sprinklr.ui
-
-import android.annotation.SuppressLint
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import com.google.accompanist.web.WebView
-import com.google.accompanist.web.rememberWebViewState
-import com.tangem.tap.features.sprinklr.ui.webview.SprinklrWebViewClient
-
-@SuppressLint("SetJavaScriptEnabled")
-@Composable
-internal fun SprinklrScreenContent(state: SprinklrScreenState, modifier: Modifier = Modifier) {
- WebView(
- modifier = modifier,
- state = rememberWebViewState(url = state.initialUrl),
- onCreated = { webView ->
- with(webView.settings) {
- javaScriptEnabled = true
- domStorageEnabled = true
- }
- },
- client = remember { SprinklrWebViewClient(state.onNewUrl) },
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenState.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenState.kt
deleted file mode 100644
index 8757f6e167..0000000000
--- a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenState.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.tangem.tap.features.sprinklr.ui
-
-import com.google.accompanist.web.WebContent
-
-internal data class SprinklrScreenState(
- val initialUrl: String = "",
- val sprinklrDomains: List = emptyList(),
- val onNavigateBack: () -> Unit = {},
- val onNewUrl: WebContent.(String) -> WebContent = { this },
-)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrViewModel.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrViewModel.kt
deleted file mode 100644
index a6cf3abe13..0000000000
--- a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrViewModel.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.tangem.tap.features.sprinklr.ui
-
-import androidx.lifecycle.ViewModel
-import com.google.accompanist.web.WebContent
-import com.tangem.core.navigation.NavigationAction
-import com.tangem.tap.common.extensions.dispatchOnMain
-import com.tangem.tap.features.sprinklr.redux.SprinklrState
-import com.tangem.tap.store
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.update
-import org.rekotlin.StoreSubscriber
-
-internal class SprinklrViewModel : ViewModel(), StoreSubscriber {
- private val stateInternal = MutableStateFlow(SprinklrScreenState())
- val state = stateInternal.asStateFlow()
-
- init {
- subscribeToStoreChanges()
- }
-
- override fun newState(state: SprinklrState) {
- stateInternal.update { prevState ->
- prevState.copy(
- initialUrl = state.url,
- sprinklrDomains = state.sprinklrDomains,
- onNewUrl = { updateWebContentOrOpenExternalUrl(it) },
- )
- }
- }
-
- override fun onCleared() {
- store.unsubscribe(this)
- }
-
- fun setNavigateBackCallback(callback: () -> Unit) {
- stateInternal.update { prevState ->
- prevState.copy(
- onNavigateBack = callback,
- )
- }
- }
-
- private fun subscribeToStoreChanges() {
- store.subscribe(this) { appState ->
- appState.skip { old, new -> old.sprinklrState == new.sprinklrState }
- .select { it.sprinklrState }
- }
- }
-
- private fun WebContent.updateWebContentOrOpenExternalUrl(url: String): WebContent {
- return if (isExternalUrl(url)) {
- store.dispatchOnMain(NavigationAction.OpenUrl(url))
- this
- } else {
- when (this) {
- is WebContent.Url -> copy(url = url)
- else -> WebContent.Url(url)
- }
- }
- }
-
- private fun isExternalUrl(url: String): Boolean {
- return state.value.sprinklrDomains.none { url.contains(it) }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/webview/SprinklrWebViewClient.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/webview/SprinklrWebViewClient.kt
deleted file mode 100644
index 2f2487c88a..0000000000
--- a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/webview/SprinklrWebViewClient.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.tangem.tap.features.sprinklr.ui.webview
-
-import android.webkit.WebResourceRequest
-import android.webkit.WebView
-import com.google.accompanist.web.AccompanistWebViewClient
-import com.google.accompanist.web.WebContent
-
-internal class SprinklrWebViewClient(
- private val onNewUrl: WebContent.(String) -> WebContent,
-) : AccompanistWebViewClient() {
-
- override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
- // If the url hasn't changed, this is probably an internal event like
- // a javascript reload. We should let it happen.
- if (view?.url == request?.url.toString()) {
- return false
- }
-
- request?.let {
- state.content = onNewUrl(state.content, it.url.toString())
- }
- return true
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt
index 889dab19e8..b4f81bd001 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt
@@ -180,7 +180,7 @@ class WalletMiddleware {
}
if (walletState.isMultiwalletAllowed) {
- val amountToSend = sendableAmounts.find { it.currencySymbol == currency.currencySymbol }
+ val amountToSend = findAmountToSend(currency = currency, amounts = sendableAmounts)
if (amountToSend == null) {
val error = TapError.UnsupportedState("WalletAction.Send: Amount to send is null")
FirebaseCrashlytics.getInstance().recordException(IllegalStateException(error.stateError))
@@ -277,6 +277,18 @@ class WalletMiddleware {
}
}
+ private fun findAmountToSend(currency: Currency, amounts: List): Amount? {
+ return amounts.find { amount ->
+ val amountType = amount.type
+ if (amountType is AmountType.Token && currency is Currency.Token) {
+ val token = amountType.token
+ token.symbol == currency.currencySymbol && token.contractAddress == currency.token.contractAddress
+ } else {
+ amount.currencySymbol == currency.currencySymbol
+ }
+ }
+ }
+
private fun makeInitSendStateActionByAmount(
amount: Amount,
walletStore: WalletStoreModel,
diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt b/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt
index 493d6b2e9e..2a1e34d105 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt
@@ -103,6 +103,7 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
amplitudeApiKey = configValues.amplitudeApiKey,
shopify = configValues.shopifyShop,
zendesk = configValues.zendesk,
+ sprinklr = configValues.sprinklr,
swapReferrerAccount = configValues.swapReferrerAccount,
walletConnectProjectId = configValues.walletConnectProjectId,
tangemComAuthorization = configValues.tangemComAuthorization,
diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/models/ChatConfig.kt b/core/datasource/src/main/java/com/tangem/datasource/config/models/ChatConfig.kt
index d34275da0f..2ab45d66bc 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/config/models/ChatConfig.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/config/models/ChatConfig.kt
@@ -23,6 +23,8 @@ data class ZendeskConfig(
data class SprinklrConfig(
@Json(name = "appID")
val appId: String,
- @Json(name = "baseURL")
- val baseUrl: String,
+ @Json(name = "apiKey")
+ val apiKey: String,
+ @Json(name = "environment")
+ val environment: String,
) : ChatConfig
\ No newline at end of file
diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt b/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt
index 3d0bf5be7f..f8fe099745 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt
@@ -16,6 +16,7 @@ data class Config(
val isCreatingTwinCardsAllowed: Boolean = false,
val shopify: ShopifyShop? = null,
val zendesk: ZendeskConfig? = null,
+ val sprinklr: SprinklrConfig? = null,
val swapReferrerAccount: SwapReferrerAccount? = null,
val walletConnectProjectId: String = "",
val tangemComAuthorization: String? = null,
diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt b/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt
index 83ffe5d09a..93210485ef 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt
@@ -32,6 +32,7 @@ class ConfigValueModel(
val appsFlyer: AppsFlyer,
val shopifyShop: ShopifyShop?,
val zendesk: ZendeskConfig?,
+ val sprinklr: SprinklrConfig?,
val tronGridApiKey: String,
val amplitudeApiKey: String,
val swapReferrerAccount: SwapReferrerAccount?,
diff --git a/data/card/src/main/java/com/tangem/data/card/DefaultCardSdkConfigRepository.kt b/data/card/src/main/java/com/tangem/data/card/DefaultCardSdkConfigRepository.kt
index 321a48b0bf..4e3b7acdef 100644
--- a/data/card/src/main/java/com/tangem/data/card/DefaultCardSdkConfigRepository.kt
+++ b/data/card/src/main/java/com/tangem/data/card/DefaultCardSdkConfigRepository.kt
@@ -49,6 +49,7 @@ internal class DefaultCardSdkConfigRepository(
ProductType.Twins -> CardIdDisplayFormat.LastLuhn(numbers = 4)
ProductType.Note,
ProductType.Wallet,
+ ProductType.Wallet2,
ProductType.Start2Coin,
-> CardIdDisplayFormat.Full
}
diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt
index 0970e85d77..3d315d3d8e 100644
--- a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt
+++ b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt
@@ -175,7 +175,6 @@ fun Blockchain.toCoinId(): String {
Blockchain.Dash -> "dash"
Blockchain.Kaspa -> "kaspa"
Blockchain.TON, Blockchain.TONTestnet -> "the-open-network"
- Blockchain.Unknown -> "unknown"
Blockchain.Kava, Blockchain.KavaTestnet -> "kava"
Blockchain.Ravencoin, Blockchain.RavencoinTestnet -> "ravencoin"
Blockchain.Cosmos, Blockchain.CosmosTestnet -> "cosmos"
@@ -185,8 +184,8 @@ fun Blockchain.toCoinId(): String {
Blockchain.Telos, Blockchain.TelosTestnet -> "telos"
Blockchain.AlephZero, Blockchain.AlephZeroTestnet -> "aleph-zero"
Blockchain.OctaSpace, Blockchain.OctaSpaceTestnet -> "octaspace"
- Blockchain.Chia -> "chia"
- Blockchain.ChiaTestnet -> "chia/test"
+ Blockchain.Chia, Blockchain.ChiaTestnet -> "chia"
+ Blockchain.Unknown -> "unknown"
}
}
diff --git a/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletBuilder.kt b/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletBuilder.kt
index 565930ae9d..b843a98ee2 100644
--- a/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletBuilder.kt
+++ b/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletBuilder.kt
@@ -20,7 +20,9 @@ class UserWalletBuilder(
ProductType.Note -> "Note"
ProductType.Twins -> "Twin"
ProductType.Start2Coin -> "Start2Coin"
- ProductType.Wallet -> when {
+ ProductType.Wallet,
+ ProductType.Wallet2,
+ -> when {
card.isBackupNotAllowed -> "Tangem card"
cardTypesResolver.isStart2Coin() -> "Start2Coin"
else -> "Wallet"
diff --git a/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletIdBuilder.kt b/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletIdBuilder.kt
index cad0957152..40ac39de3c 100644
--- a/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletIdBuilder.kt
+++ b/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletIdBuilder.kt
@@ -60,6 +60,7 @@ class UserWalletIdBuilder private constructor(
ProductType.Twins -> scanResponse.secondTwinPublicKey?.hexToBytes()
ProductType.Note,
ProductType.Wallet,
+ ProductType.Wallet2,
ProductType.Start2Coin,
-> null
},
diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/scan/ScanResponse.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/scan/ScanResponse.kt
index c6f1d9f75c..74a552e520 100644
--- a/domain/models/src/main/kotlin/com/tangem/domain/models/scan/ScanResponse.kt
+++ b/domain/models/src/main/kotlin/com/tangem/domain/models/scan/ScanResponse.kt
@@ -21,5 +21,5 @@ data class ScanResponse(
typealias KeyWalletPublicKey = ByteArrayKey
enum class ProductType {
- Note, Twins, Wallet, Start2Coin
+ Note, Twins, Wallet, Start2Coin, Wallet2
}
\ No newline at end of file
diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml
index d4c76f2594..843863953e 100644
--- a/gradle/dependencies.toml
+++ b/gradle/dependencies.toml
@@ -78,10 +78,11 @@ walletConnectCore = "1.18.0"
walletConnectWeb3 = "1.11.0"
prettyLogger = "2.2.0"
okHttp-prettyLogging = "3.1.0"
+spr-client = "3.6.2"
# endregion Other libraries
# region Tangem
-tangemBlockchainSdk = "release-app_4.11-349"
+tangemBlockchainSdk = "release-app_4.11-360"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "release-app_4.11-295"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds
@@ -227,4 +228,5 @@ reactive-network = { module = "com.github.pwittchen:reactivenetwork-rx2", versio
walletConnectCore = { module = "com.walletconnect:android-core", version.ref = "walletConnectCore" }
walletConnectWeb3 = { module = "com.walletconnect:web3wallet", version.ref = "walletConnectWeb3" }
prettyLogger = { module = "com.orhanobut:logger", version.ref = "prettyLogger" }
+sprClient = { module = "com.spr:messengerclient", version.ref = "spr-client" }
# endregion Other
diff --git a/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/extension/AppExtensionConfigurations.kt b/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/extension/AppExtensionConfigurations.kt
index 1ba8b81a2d..05b2b465c2 100644
--- a/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/extension/AppExtensionConfigurations.kt
+++ b/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/extension/AppExtensionConfigurations.kt
@@ -76,6 +76,7 @@ private fun AndroidBuildType.configureBuildVariant(extension: AppExtension, buil
BuildType.External,
-> {
initWith(extension.buildTypes.getByName(BuildType.Release.id))
+ matchingFallbacks.add(BuildType.Release.id)
signingConfig = extension.signingConfigs.getByName(BuildType.Debug.id)
}
}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index b2c3126321..7e4c66d7d8 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -40,6 +40,7 @@ dependencyResolutionManagement {
}
maven("https://jitpack.io")
maven("https://zendesk.jfrog.io/zendesk/repo")
+ maven("https://clients-nexus.sprinklr.com/")
}
versionCatalogs {